Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,16 @@
* <li>FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.</li>
* <li>FOUNDRY_MODEL_NAME - The model deployment name.</li>
* <li>FABRIC_IQ_PROJECT_CONNECTION_ID - The FabricIQ connection ID.</li>
* <li>FABRIC_IQ_USER_INPUT - Optional. The natural-language question to send to the agent.</li>
* </ul>
*/
public class FabricIQAsync {
public static void main(String[] args) {
String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT");
String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_NAME");
String fabricIqConnectionId = Configuration.getGlobalConfiguration().get("FABRIC_IQ_PROJECT_CONNECTION_ID");
String userInput = Configuration.getGlobalConfiguration().get("FABRIC_IQ_USER_INPUT",
"Use FabricIQ to summarize the available enterprise context.");

AgentsClientBuilder builder = new AgentsClientBuilder()
.credential(new DefaultAzureCredentialBuilder().build())
Expand All @@ -51,10 +54,10 @@ public static void main(String[] args) {
.setDescription("Use FabricIQ to answer questions grounded in enterprise data.");

PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model)
.setInstructions("You are a data assistant that can use FabricIQ for grounded enterprise answers.")
.setInstructions("Use the available Fabric IQ tools to answer questions and perform tasks.")
.setTools(Collections.singletonList(fabricIqTool));

agentsAsyncClient.createAgentVersion("fabric-iq-async-agent", agentDefinition)
agentsAsyncClient.createAgentVersion("fabric-iq-agent", agentDefinition)
.flatMap(agent -> {
agentRef.set(agent);
System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion());
Expand All @@ -65,7 +68,7 @@ public static void main(String[] args) {
return responsesAsyncClient.createAzureResponse(
new AzureCreateResponseOptions().setAgentReference(agentReference),
ResponseCreateParams.builder()
.input("Use FabricIQ to summarize the available enterprise context."));
.input(userInput));
})
.doOnNext(response -> System.out.println("Response: " + response.output()))
.then(Mono.defer(() -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,16 @@
* <li>FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint.</li>
* <li>FOUNDRY_MODEL_NAME - The model deployment name.</li>
* <li>FABRIC_IQ_PROJECT_CONNECTION_ID - The FabricIQ connection ID.</li>
* <li>FABRIC_IQ_USER_INPUT - Optional. The natural-language question to send to the agent.</li>
* </ul>
*/
public class FabricIQSync {
public static void main(String[] args) {
String endpoint = Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT");
String model = Configuration.getGlobalConfiguration().get("FOUNDRY_MODEL_NAME");
String fabricIqConnectionId = Configuration.getGlobalConfiguration().get("FABRIC_IQ_PROJECT_CONNECTION_ID");
String userInput = Configuration.getGlobalConfiguration().get("FABRIC_IQ_USER_INPUT",
"Use FabricIQ to summarize the available enterprise context.");

AgentsClientBuilder builder = new AgentsClientBuilder()
.credential(new DefaultAzureCredentialBuilder().build())
Expand All @@ -52,7 +55,7 @@ public static void main(String[] args) {
// END: com.azure.ai.agents.define_fabric_iq

PromptAgentDefinition agentDefinition = new PromptAgentDefinition(model)
.setInstructions("You are a data assistant that can use FabricIQ for grounded enterprise answers.")
.setInstructions("Use the available Fabric IQ tools to answer questions and perform tasks.")
.setTools(Collections.singletonList(fabricIqTool));

AgentVersionDetails agent = agentsClient.createAgentVersion("fabric-iq-agent", agentDefinition);
Expand All @@ -65,7 +68,7 @@ public static void main(String[] args) {
Response response = responsesClient.createAzureResponse(
new AzureCreateResponseOptions().setAgentReference(agentReference),
ResponseCreateParams.builder()
.input("Use FabricIQ to summarize the available enterprise context."));
.input(userInput));

System.out.println("Response: " + response.output());
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ protected AgentsClientBuilder getClientBuilder(HttpClient httpClient, AgentsServ
builder.endpoint("https://localhost:8080").credential(new MockTokenCredential());
} else if (testMode == TestMode.RECORD) {
builder.addPolicy(interceptorManager.getRecordPolicy())
.endpoint(Configuration.getGlobalConfiguration().get("AZURE_AGENTS_ENDPOINT"))
.endpoint(Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"))
.credential(new DefaultAzureCredentialBuilder().build());
} else {
builder.endpoint(Configuration.getGlobalConfiguration().get("AZURE_AGENTS_ENDPOINT"))
builder.endpoint(Configuration.getGlobalConfiguration().get("FOUNDRY_PROJECT_ENDPOINT"))
.credential(new DefaultAzureCredentialBuilder().build());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.ai.agents.tools;

import com.azure.ai.agents.AgentsAsyncClient;
import com.azure.ai.agents.AgentsClientBuilder;
import com.azure.ai.agents.AgentsServiceVersion;
import com.azure.ai.agents.ResponsesAsyncClient;
import com.azure.ai.agents.models.AgentReference;
import com.azure.ai.agents.models.AgentVersionDetails;
import com.azure.ai.agents.models.AzureCreateResponseOptions;
import com.azure.core.http.HttpClient;
import com.openai.models.responses.Response;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Timeout;
import org.junit.jupiter.api.parallel.ResourceLock;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import java.time.Duration;
import java.util.concurrent.TimeUnit;

public class FabricIQSamplesAsyncTests extends FabricIQSamplesTestBase {

@Timeout(value = 5, unit = TimeUnit.MINUTES)
@Disabled("getting 500 from service")
@ResourceLock(FABRIC_IQ_RESOURCE_LOCK)
@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
@MethodSource("getTestParameters")
public void fabricIqAsyncSample(HttpClient httpClient, AgentsServiceVersion serviceVersion) {
AgentsClientBuilder builder = getClientBuilder(httpClient, serviceVersion);
AgentsAsyncClient agentsAsyncClient = builder.buildAgentsAsyncClient();
ResponsesAsyncClient responsesAsyncClient = builder.buildResponsesAsyncClient();

String agentName = testResourceNamer.randomName("fabric-iq-async-", 40);
AgentVersionDetails agent
= agentsAsyncClient.createAgentVersion(agentName, createAgentDefinition()).block(Duration.ofMinutes(2));
Assertions.assertNotNull(agent);

AgentReference agentReference = new AgentReference(agent.getName()).setVersion(agent.getVersion());
Response response
= responsesAsyncClient
.createAzureResponse(new AzureCreateResponseOptions().setAgentReference(agentReference),
createResponseParams())
.block(Duration.ofMinutes(3));

assertCompletedResponse(response);
agentsAsyncClient.deleteAgentVersion(agent.getName(), agent.getVersion()).block(Duration.ofMinutes(1));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.ai.agents.tools;

import com.azure.ai.agents.AgentsServiceVersion;
import com.azure.ai.agents.ClientTestBase;
import com.azure.ai.agents.models.FabricIQPreviewTool;
import com.azure.ai.agents.models.PromptAgentDefinition;
import com.azure.core.test.TestMode;
import com.azure.core.util.Configuration;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseStatus;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.params.provider.Arguments;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;

import static com.azure.core.test.TestProxyTestBase.getHttpClients;

abstract class FabricIQSamplesTestBase extends ClientTestBase {
static final String DISPLAY_NAME_WITH_ARGUMENTS = "{displayName} with [{arguments}]";
static final String FABRIC_IQ_RESOURCE_LOCK = "fabric-iq";

private static final String DEFAULT_USER_INPUT = "Tell me weather history in London, Ohio";

static Stream<Arguments> getTestParameters() {
List<Arguments> argumentsList = new ArrayList<>();
getHttpClients().forEach(httpClient -> argumentsList.add(Arguments.of(httpClient, AgentsServiceVersion.V1)));
return argumentsList.stream();
}

PromptAgentDefinition createAgentDefinition() {
FabricIQPreviewTool fabricIqTool
= new FabricIQPreviewTool(getRecordedConfig("FABRIC_IQ_PROJECT_CONNECTION_ID")).setRequireApproval("never");

return new PromptAgentDefinition(getRecordedConfig("FOUNDRY_MODEL_NAME"))
.setInstructions("Use the available Fabric IQ tools to answer questions and perform tasks.")
.setTools(Collections.singletonList(fabricIqTool));
}

String getUserInput() {
return Configuration.getGlobalConfiguration().get("FABRIC_IQ_USER_INPUT", DEFAULT_USER_INPUT);
}

ResponseCreateParams.Builder createResponseParams() {
return ResponseCreateParams.builder().input(getUserInput());
}

void assertCompletedResponse(Response response) {
Assertions.assertNotNull(response);
Assertions.assertTrue(response.status().isPresent());
Assertions.assertEquals(ResponseStatus.COMPLETED, response.status().get());
Assertions.assertFalse(response.output().isEmpty());
Assertions.assertTrue(response.output().stream().anyMatch(item -> item.isMessage()));
}

private String getRecordedConfig(String name) {
if (getTestMode() == TestMode.PLAYBACK) {
return testResourceNamer.recordValueFromConfig(name);
}

String value = Configuration.getGlobalConfiguration().get(name);
if (getTestMode() == TestMode.RECORD) {
testResourceNamer.recordValueFromConfig(name);
}
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,45 @@

package com.azure.ai.agents.tools;

import com.azure.ai.agents.AgentsClient;
import com.azure.ai.agents.AgentsClientBuilder;
import com.azure.ai.agents.AgentsServiceVersion;
import com.azure.ai.agents.ClientTestBase;
import com.azure.ai.agents.ResponsesClient;
import com.azure.core.http.HttpClient;
import org.junit.jupiter.api.Disabled;
import com.azure.ai.agents.models.AgentReference;
import com.azure.ai.agents.models.AgentVersionDetails;
import com.azure.ai.agents.models.AzureCreateResponseOptions;
import com.openai.models.responses.Response;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Timeout;
import org.junit.jupiter.api.parallel.ResourceLock;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

import static com.azure.core.test.TestProxyTestBase.getHttpClients;
import java.util.concurrent.TimeUnit;

public class FabricIQSamplesTests extends ClientTestBase {
private static final String DISPLAY_NAME_WITH_ARGUMENTS = "{displayName} with [{arguments}]";

static Stream<Arguments> getTestParameters() {
List<Arguments> argumentsList = new ArrayList<>();
getHttpClients().forEach(httpClient -> argumentsList.add(Arguments.of(httpClient, AgentsServiceVersion.V1)));
return argumentsList.stream();
}
public class FabricIQSamplesTests extends FabricIQSamplesTestBase {

@Disabled("Requires FABRIC_IQ_PROJECT_CONNECTION_ID and FOUNDRY_MODEL_NAME.")
@Timeout(value = 5, unit = TimeUnit.MINUTES)
@Disabled("getting 500 from service")
@ResourceLock(FABRIC_IQ_RESOURCE_LOCK)
@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
@MethodSource("getTestParameters")
public void fabricIqSyncSample(HttpClient httpClient, AgentsServiceVersion serviceVersion) {
Assertions.fail("Enable after providing FABRIC_IQ_PROJECT_CONNECTION_ID and FOUNDRY_MODEL_NAME.");
}
AgentsClientBuilder builder = getClientBuilder(httpClient, serviceVersion);
AgentsClient agentsClient = builder.buildAgentsClient();
ResponsesClient responsesClient = builder.buildResponsesClient();

@Disabled("Requires FABRIC_IQ_PROJECT_CONNECTION_ID and FOUNDRY_MODEL_NAME.")
@ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS)
@MethodSource("getTestParameters")
public void fabricIqAsyncSample(HttpClient httpClient, AgentsServiceVersion serviceVersion) {
Assertions.fail("Enable after providing FABRIC_IQ_PROJECT_CONNECTION_ID and FOUNDRY_MODEL_NAME.");
String agentName = testResourceNamer.randomName("fabric-iq-sync-", 40);
AgentVersionDetails agent = agentsClient.createAgentVersion(agentName, createAgentDefinition());
Assertions.assertNotNull(agent);

AgentReference agentReference = new AgentReference(agent.getName());
Response response = responsesClient.createAzureResponse(
new AzureCreateResponseOptions().setAgentReference(agentReference), createResponseParams());

assertCompletedResponse(response);
agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion());
}
}
18 changes: 18 additions & 0 deletions sdk/ai/azure-ai-projects/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,24 @@ EvalService evalService = builder.buildOpenAIClient().evals();
EvalServiceAsync evalAsyncService = builder.buildOpenAIAsyncClient().evals();
```

When using Azure-specific evaluator models with OpenAI evaluations, use `EvaluationsHelper` to adapt the Azure model to
the OpenAI request type. This keeps application code from depending on the serialization details used by the OpenAI SDK.

```java com.azure.ai.projects.evaluationsHelper
Map<String, String> dataMapping = new LinkedHashMap<>();
dataMapping.put("query", "{{item.query}}");
dataMapping.put("response", "{{sample.output_text}}");

TestingCriterionAzureAIEvaluator coherenceEvaluator = new TestingCriterionAzureAIEvaluator("coherence",
"builtin.coherence")
.setInitializationParameters(Collections.singletonMap("deployment_name",
BinaryData.fromObject("gpt-4o-mini")))
.setDataMapping(dataMapping);

EvalCreateParams.TestingCriterion testingCriterion
= EvaluationsHelper.toTestingCriterion(coherenceEvaluator);
```

For the Agents operation, you can use the `azure-ai-agents` package which is available as transitive dependency:

```java com.azure.ai.projects.agentsSubClients
Expand Down
2 changes: 1 addition & 1 deletion sdk/ai/azure-ai-projects/assets.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"AssetsRepo":"Azure/azure-sdk-assets","AssetsRepoPrefixPath":"java","TagPrefix":"java/ai/azure-ai-projects","Tag": "java/ai/azure-ai-projects_cd9e4bffa9"}
{"AssetsRepo":"Azure/azure-sdk-assets","AssetsRepoPrefixPath":"java","TagPrefix":"java/ai/azure-ai-projects","Tag": "java/ai/azure-ai-projects_c4dd2a11a3"}
1 change: 1 addition & 0 deletions sdk/ai/azure-ai-projects/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ Code generated by Microsoft (R) TypeSpec Code Generator.
--add-exports com.azure.core/com.azure.core.implementation.util=ALL-UNNAMED
--add-opens com.azure.core/com.azure.core.implementation.util=ALL-UNNAMED
</javaModulesSurefireArgLine>
<surefire.useModulePath>false</surefire.useModulePath>
</properties>
<dependencies>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.ai.projects;

import com.azure.ai.projects.implementation.OpenAIJsonHelper;
import com.azure.ai.projects.models.TestingCriterionAzureAIEvaluator;
import com.openai.models.evals.EvalCreateParams;

/**
* Helper methods for Azure AI evaluations.
*/
public final class EvaluationsHelper {
private EvaluationsHelper() {
}

/**
* Converts an Azure AI evaluator model to an OpenAI evaluation testing criterion.
*
* <p>Use this helper when creating OpenAI evaluations with Azure-specific evaluator types such as
* {@link TestingCriterionAzureAIEvaluator}. The helper preserves the Azure evaluator wire shape while hiding the
* serialization details needed to pass it to the OpenAI SDK.</p>
*
* @param evaluator The Azure AI evaluator to use as an evaluation testing criterion.
* @return The OpenAI evaluation testing criterion.
* @throws NullPointerException if {@code evaluator} is null.
*/
public static EvalCreateParams.TestingCriterion toTestingCriterion(TestingCriterionAzureAIEvaluator evaluator) {
return OpenAIJsonHelper.toOpenAIType(evaluator, EvalCreateParams.TestingCriterion.class);
}
}
Loading