mirror of
https://github.com/microsoft/semantic-kernel.git
synced 2026-10-12 02:19:06 +00:00
Merge branch 'main' into taochen/python-invoke-model-after-auto-invoke-exhausted
This commit is contained in:
@@ -32,6 +32,7 @@ extend-exclude = [
|
||||
|
||||
[default.extend-words]
|
||||
ACI = "ACI" # Azure Container Instance
|
||||
CPY = "CPY" # Ruff copyright lint rule prefix
|
||||
exercize = "exercize" # test typos
|
||||
gramatical = "gramatical" # test typos
|
||||
Guid = "Guid" # Globally Unique Identifier
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
name: Get GitHub automation token
|
||||
description: Creates a GitHub App installation token with a temporary PAT fallback
|
||||
|
||||
inputs:
|
||||
mode:
|
||||
description: Authentication mode (app, app-with-fallback, or pat)
|
||||
required: false
|
||||
default: app-with-fallback
|
||||
azure-client-id:
|
||||
description: Client ID of the Azure workload identity
|
||||
required: false
|
||||
azure-tenant-id:
|
||||
description: Azure tenant ID
|
||||
required: false
|
||||
azure-subscription-id:
|
||||
description: Azure subscription containing the Key Vault
|
||||
required: false
|
||||
key-vault-name:
|
||||
description: Azure Key Vault name
|
||||
required: false
|
||||
key-name:
|
||||
description: Key Vault key used to sign the GitHub App JWT
|
||||
required: false
|
||||
github-app-client-id:
|
||||
description: GitHub App client ID
|
||||
required: false
|
||||
github-app-installation-id:
|
||||
description: GitHub App installation ID
|
||||
required: false
|
||||
repository:
|
||||
description: Repository to include in the installation token
|
||||
required: false
|
||||
permission-profile:
|
||||
description: Permission profile (issues, pull-requests, or devflow)
|
||||
required: true
|
||||
fallback-token:
|
||||
description: PAT used temporarily when app authentication is unavailable
|
||||
required: false
|
||||
|
||||
outputs:
|
||||
token:
|
||||
description: GitHub App installation token or fallback PAT
|
||||
value: ${{ steps.select-token.outputs.token }}
|
||||
source:
|
||||
description: Selected authentication source
|
||||
value: ${{ steps.select-token.outputs.source }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Validate authentication mode
|
||||
shell: bash
|
||||
env:
|
||||
AUTH_MODE: ${{ inputs.mode || 'app-with-fallback' }}
|
||||
run: |
|
||||
if [[ "$AUTH_MODE" != "app" && "$AUTH_MODE" != "app-with-fallback" && "$AUTH_MODE" != "pat" ]]; then
|
||||
echo "::error::Unsupported GitHub authentication mode."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Sign in to Azure
|
||||
id: azure-login
|
||||
if: ${{ (inputs.mode || 'app-with-fallback') != 'pat' }}
|
||||
continue-on-error: true
|
||||
uses: azure/login@7ddb5af1ef8758cf1353cf3b42f940aee27ba21c # v3.0.2
|
||||
with:
|
||||
client-id: ${{ inputs.azure-client-id }}
|
||||
tenant-id: ${{ inputs.azure-tenant-id }}
|
||||
subscription-id: ${{ inputs.azure-subscription-id }}
|
||||
|
||||
- name: Create GitHub App installation token
|
||||
id: app-token
|
||||
if: ${{ (inputs.mode || 'app-with-fallback') != 'pat' && steps.azure-login.outcome == 'success' }}
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
env:
|
||||
AZURE_SUBSCRIPTION_ID: ${{ inputs.azure-subscription-id }}
|
||||
KEY_VAULT_NAME: ${{ inputs.key-vault-name }}
|
||||
KEY_NAME: ${{ inputs.key-name }}
|
||||
GITHUB_APP_CLIENT_ID: ${{ inputs.github-app-client-id }}
|
||||
GITHUB_APP_INSTALLATION_ID: ${{ inputs.github-app-installation-id }}
|
||||
TARGET_REPOSITORY: ${{ inputs.repository }}
|
||||
PERMISSION_PROFILE: ${{ inputs.permission-profile }}
|
||||
run: |
|
||||
token="$(node "$GITHUB_ACTION_PATH/create-token.js")"
|
||||
echo "::add-mask::$token"
|
||||
echo "token=$token" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Select authentication token
|
||||
id: select-token
|
||||
shell: bash
|
||||
env:
|
||||
AUTH_MODE: ${{ inputs.mode || 'app-with-fallback' }}
|
||||
APP_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
FALLBACK_TOKEN: ${{ inputs.fallback-token }}
|
||||
run: |
|
||||
if [[ "$AUTH_MODE" != "pat" && -n "$APP_TOKEN" ]]; then
|
||||
token="$APP_TOKEN"
|
||||
source="app"
|
||||
echo "::notice::GitHub authentication source: app"
|
||||
elif [[ "$AUTH_MODE" == "app-with-fallback" && -n "$FALLBACK_TOKEN" ]]; then
|
||||
token="$FALLBACK_TOKEN"
|
||||
source="pat-fallback"
|
||||
echo "::warning::GitHub authentication source: PAT fallback"
|
||||
elif [[ "$AUTH_MODE" == "pat" && -n "$FALLBACK_TOKEN" ]]; then
|
||||
token="$FALLBACK_TOKEN"
|
||||
source="pat-forced"
|
||||
echo "::warning::GitHub authentication source: PAT (forced rollout mode)"
|
||||
else
|
||||
echo "::error::GitHub App authentication is unavailable and no fallback PAT was provided."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "::add-mask::$token"
|
||||
echo "token=$token" >> "$GITHUB_OUTPUT"
|
||||
echo "source=$source" >> "$GITHUB_OUTPUT"
|
||||
@@ -0,0 +1,149 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
const crypto = require('node:crypto');
|
||||
const { execFileSync } = require('node:child_process');
|
||||
|
||||
const PERMISSION_PROFILES = Object.freeze({
|
||||
issues: Object.freeze({
|
||||
issues: 'write',
|
||||
}),
|
||||
'pull-requests': Object.freeze({
|
||||
contents: 'read',
|
||||
pull_requests: 'write',
|
||||
}),
|
||||
devflow: Object.freeze({
|
||||
contents: 'read',
|
||||
issues: 'write',
|
||||
pull_requests: 'write',
|
||||
}),
|
||||
});
|
||||
|
||||
function base64Url(value) {
|
||||
return Buffer.from(value).toString('base64url');
|
||||
}
|
||||
|
||||
function base64ToBase64Url(value) {
|
||||
return Buffer.from(value, 'base64').toString('base64url');
|
||||
}
|
||||
|
||||
function createJwtSigningInput(clientId, nowSeconds) {
|
||||
const header = base64Url(JSON.stringify({ alg: 'RS256', typ: 'JWT' }));
|
||||
const payload = base64Url(JSON.stringify({
|
||||
iat: nowSeconds - 60,
|
||||
exp: nowSeconds + 540,
|
||||
iss: clientId,
|
||||
}));
|
||||
return `${header}.${payload}`;
|
||||
}
|
||||
|
||||
function signJwt(signingInput, config, execute = execFileSync) {
|
||||
const digest = crypto.createHash('sha256').update(signingInput).digest('base64');
|
||||
const signature = execute(
|
||||
'az',
|
||||
[
|
||||
'keyvault', 'key', 'sign',
|
||||
'--subscription', config.azureSubscriptionId,
|
||||
'--vault-name', config.keyVaultName,
|
||||
'--name', config.keyName,
|
||||
'--algorithm', 'RS256',
|
||||
'--digest', digest,
|
||||
'--query', 'signature',
|
||||
'--output', 'tsv',
|
||||
'--only-show-errors',
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
).trim();
|
||||
|
||||
if (!signature) {
|
||||
throw new Error('Key Vault returned an empty signature.');
|
||||
}
|
||||
|
||||
return `${signingInput}.${base64ToBase64Url(signature)}`;
|
||||
}
|
||||
|
||||
async function createInstallationToken(config, dependencies = {}) {
|
||||
const execute = dependencies.execute ?? execFileSync;
|
||||
const request = dependencies.fetch ?? fetch;
|
||||
const nowSeconds = dependencies.nowSeconds ?? Math.floor(Date.now() / 1000);
|
||||
const repositoryParts = config.targetRepository.split('/');
|
||||
|
||||
if (repositoryParts.length !== 2 || repositoryParts.some((part) => part.length === 0)) {
|
||||
throw new Error('TARGET_REPOSITORY must use the owner/repository format.');
|
||||
}
|
||||
if (!Object.hasOwn(PERMISSION_PROFILES, config.permissionProfile)) {
|
||||
throw new Error('PERMISSION_PROFILE must be issues, pull-requests, or devflow.');
|
||||
}
|
||||
const permissions = PERMISSION_PROFILES[config.permissionProfile];
|
||||
|
||||
const [, repository] = repositoryParts;
|
||||
const signingInput = createJwtSigningInput(config.githubAppClientId, nowSeconds);
|
||||
const jwt = signJwt(signingInput, config, execute);
|
||||
|
||||
const response = await request(
|
||||
`https://api.github.com/app/installations/${config.githubAppInstallationId}/access_tokens`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Accept: 'application/vnd.github+json',
|
||||
Authorization: `Bearer ${jwt}`,
|
||||
'X-GitHub-Api-Version': '2022-11-28',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
repositories: [repository],
|
||||
permissions,
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`GitHub installation token request failed with HTTP ${response.status}.`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
if (typeof result.token !== 'string' || result.token.length === 0) {
|
||||
throw new Error('GitHub returned an empty installation token.');
|
||||
}
|
||||
|
||||
return result.token;
|
||||
}
|
||||
|
||||
function readConfig(environment) {
|
||||
const config = {
|
||||
azureSubscriptionId: environment.AZURE_SUBSCRIPTION_ID,
|
||||
keyVaultName: environment.KEY_VAULT_NAME,
|
||||
keyName: environment.KEY_NAME,
|
||||
githubAppClientId: environment.GITHUB_APP_CLIENT_ID,
|
||||
githubAppInstallationId: environment.GITHUB_APP_INSTALLATION_ID,
|
||||
targetRepository: environment.TARGET_REPOSITORY,
|
||||
permissionProfile: environment.PERMISSION_PROFILE,
|
||||
};
|
||||
|
||||
if (Object.values(config).some((value) => !value)) {
|
||||
throw new Error('Required GitHub App authentication configuration is missing.');
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
const token = await createInstallationToken(readConfig(process.env));
|
||||
process.stdout.write(token);
|
||||
} catch {
|
||||
console.error('GitHub App token generation failed.');
|
||||
process.exitCode = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
void main();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
base64ToBase64Url,
|
||||
createInstallationToken,
|
||||
createJwtSigningInput,
|
||||
readConfig,
|
||||
signJwt,
|
||||
PERMISSION_PROFILES,
|
||||
};
|
||||
@@ -42,3 +42,5 @@ updates:
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
day: "tuesday"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
|
||||
+30
-17
@@ -1,43 +1,56 @@
|
||||
# Add 'kernel' label to any change within Connectors, Extensions, Skills, and tests directories
|
||||
kernel:
|
||||
- dotnet/src/Connectors/**/*
|
||||
- dotnet/src/Extensions/**/*
|
||||
- dotnet/src/Skills/**/*
|
||||
- dotnet/src/IntegrationTests/**/*
|
||||
- dotnet/src/SemanticKernel.UnitTests/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- dotnet/src/Connectors/**/*
|
||||
- dotnet/src/Extensions/**/*
|
||||
- dotnet/src/Skills/**/*
|
||||
- dotnet/src/IntegrationTests/**/*
|
||||
- dotnet/src/SemanticKernel.UnitTests/**/*
|
||||
|
||||
# Add 'kernel.core' label to any change within the 'SemanticKernel', 'SemanticKernel.Abstractions', or 'SemanticKernel.MetaPackage' directories
|
||||
kernel.core:
|
||||
- dotnet/src/SemanticKernel/**/*
|
||||
- dotnet/src/SemanticKernel.Abstractions/**/*
|
||||
- dotnet/src/SemanticKernel.MetaPackage/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- dotnet/src/SemanticKernel/**/*
|
||||
- dotnet/src/SemanticKernel.Abstractions/**/*
|
||||
- dotnet/src/SemanticKernel.MetaPackage/**/*
|
||||
|
||||
# Add 'python' label to any change within the 'python' directory
|
||||
python:
|
||||
- python/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: python/**/*
|
||||
|
||||
# Add 'java' label to any change within the 'java' directory
|
||||
java:
|
||||
- java/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: java/**/*
|
||||
|
||||
# Add 'samples' label to any change within the 'samples' directory
|
||||
samples:
|
||||
- samples/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: samples/**/*
|
||||
|
||||
# Add '.NET' label to any change within samples or kernel 'dotnet' directories.
|
||||
.NET:
|
||||
- dotnet/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: dotnet/**/*
|
||||
|
||||
# Add 'copilot chat' label to any change within the 'samples/apps/copilot-chat-app' directory
|
||||
copilot chat:
|
||||
- samples/apps/copilot-chat-app/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: samples/apps/copilot-chat-app/**/*
|
||||
|
||||
# Add 'documentation' label to any change within the 'docs' directory, or any '.md' files
|
||||
documentation:
|
||||
- docs/**/*
|
||||
- '**/*.md'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- docs/**/*
|
||||
- '**/*.md'
|
||||
|
||||
# Add 'memory' label to any memory connectors in dotnet/ or python/
|
||||
memory:
|
||||
- dotnet/src/Connectors/Connectors.Memory.*/**/*
|
||||
- python/semantic_kernel/connectors/memory/**/*
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- dotnet/src/Connectors/Connectors.Memory.*/**/*
|
||||
- python/semantic_kernel/connectors/memory/**/*
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
const { describe, it } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
|
||||
const {
|
||||
base64ToBase64Url,
|
||||
createInstallationToken,
|
||||
createJwtSigningInput,
|
||||
readConfig,
|
||||
} = require('../actions/github-app-token/create-token.js');
|
||||
|
||||
const CONFIG = {
|
||||
azureSubscriptionId: 'subscription-id',
|
||||
keyVaultName: 'vault-name',
|
||||
keyName: 'key-name',
|
||||
githubAppClientId: 'client-id',
|
||||
githubAppInstallationId: '12345',
|
||||
targetRepository: 'microsoft/semantic-kernel',
|
||||
permissionProfile: 'devflow',
|
||||
};
|
||||
|
||||
describe('GitHub App token creation', () => {
|
||||
it('creates a short-lived GitHub App JWT', () => {
|
||||
const signingInput = createJwtSigningInput('client-id', 1_000);
|
||||
const [encodedHeader, encodedPayload] = signingInput.split('.');
|
||||
const header = JSON.parse(Buffer.from(encodedHeader, 'base64url').toString());
|
||||
const payload = JSON.parse(Buffer.from(encodedPayload, 'base64url').toString());
|
||||
|
||||
assert.deepEqual(header, { alg: 'RS256', typ: 'JWT' });
|
||||
assert.deepEqual(payload, { iat: 940, exp: 1_540, iss: 'client-id' });
|
||||
});
|
||||
|
||||
it('converts Key Vault signatures to unpadded base64url', () => {
|
||||
assert.equal(base64ToBase64Url('+/8='), '-_8');
|
||||
});
|
||||
|
||||
it('requests a repository-scoped installation token', async () => {
|
||||
let request;
|
||||
const token = await createInstallationToken(CONFIG, {
|
||||
nowSeconds: 1_000,
|
||||
execute: (command, args) => {
|
||||
assert.equal(command, 'az');
|
||||
assert.ok(args.includes('RS256'));
|
||||
return '+/8=\n';
|
||||
},
|
||||
fetch: async (url, options) => {
|
||||
request = { url, options };
|
||||
return {
|
||||
ok: true,
|
||||
json: async () => ({ token: 'installation-token' }),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(token, 'installation-token');
|
||||
assert.equal(request.url, 'https://api.github.com/app/installations/12345/access_tokens');
|
||||
assert.match(request.options.headers.Authorization, /^Bearer [^.]+\.[^.]+\.-_8$/);
|
||||
assert.deepEqual(JSON.parse(request.options.body), {
|
||||
repositories: ['semantic-kernel'],
|
||||
permissions: {
|
||||
contents: 'read',
|
||||
issues: 'write',
|
||||
pull_requests: 'write',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('limits issue-label tokens to issue writes', async () => {
|
||||
let request;
|
||||
await createInstallationToken(
|
||||
{ ...CONFIG, permissionProfile: 'issues' },
|
||||
{
|
||||
execute: () => '+/8=\n',
|
||||
fetch: async (_url, options) => {
|
||||
request = options;
|
||||
return {
|
||||
ok: true,
|
||||
json: async () => ({ token: 'installation-token' }),
|
||||
};
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
assert.deepEqual(JSON.parse(request.body).permissions, {
|
||||
issues: 'write',
|
||||
});
|
||||
});
|
||||
|
||||
it('limits pull-request label tokens to contents and pull requests', async () => {
|
||||
let request;
|
||||
await createInstallationToken(
|
||||
{ ...CONFIG, permissionProfile: 'pull-requests' },
|
||||
{
|
||||
execute: () => '+/8=\n',
|
||||
fetch: async (_url, options) => {
|
||||
request = options;
|
||||
return {
|
||||
ok: true,
|
||||
json: async () => ({ token: 'installation-token' }),
|
||||
};
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
assert.deepEqual(JSON.parse(request.body).permissions, {
|
||||
contents: 'read',
|
||||
pull_requests: 'write',
|
||||
});
|
||||
});
|
||||
|
||||
it('rejects unknown permission profiles before signing', async () => {
|
||||
let signed = false;
|
||||
|
||||
await assert.rejects(
|
||||
createInstallationToken(
|
||||
{ ...CONFIG, permissionProfile: 'everything' },
|
||||
{
|
||||
execute: () => {
|
||||
signed = true;
|
||||
return '+/8=\n';
|
||||
},
|
||||
},
|
||||
),
|
||||
/PERMISSION_PROFILE must be issues, pull-requests, or devflow/,
|
||||
);
|
||||
assert.equal(signed, false);
|
||||
});
|
||||
|
||||
it('rejects inherited object properties as permission profiles before signing', async () => {
|
||||
let signed = false;
|
||||
|
||||
await assert.rejects(
|
||||
createInstallationToken(
|
||||
{ ...CONFIG, permissionProfile: 'toString' },
|
||||
{
|
||||
execute: () => {
|
||||
signed = true;
|
||||
return '+/8=\n';
|
||||
},
|
||||
},
|
||||
),
|
||||
/PERMISSION_PROFILE must be issues, pull-requests, or devflow/,
|
||||
);
|
||||
assert.equal(signed, false);
|
||||
});
|
||||
|
||||
it('rejects incomplete configuration', () => {
|
||||
assert.throws(
|
||||
() => readConfig({}),
|
||||
/Required GitHub App authentication configuration is missing/,
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects repository values with extra path segments before signing', async () => {
|
||||
let signed = false;
|
||||
|
||||
await assert.rejects(
|
||||
createInstallationToken(
|
||||
{ ...CONFIG, targetRepository: 'microsoft/semantic-kernel/extra' },
|
||||
{
|
||||
execute: () => {
|
||||
signed = true;
|
||||
return '+/8=\n';
|
||||
},
|
||||
},
|
||||
),
|
||||
/TARGET_REPOSITORY must use the owner\/repository format/,
|
||||
);
|
||||
assert.equal(signed, false);
|
||||
});
|
||||
|
||||
it('rejects an empty Key Vault signature', async () => {
|
||||
await assert.rejects(
|
||||
createInstallationToken(CONFIG, {
|
||||
execute: () => '\n',
|
||||
}),
|
||||
/Key Vault returned an empty signature/,
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects a failed GitHub token request', async () => {
|
||||
await assert.rejects(
|
||||
createInstallationToken(CONFIG, {
|
||||
execute: () => '+/8=\n',
|
||||
fetch: async () => ({ ok: false, status: 403 }),
|
||||
}),
|
||||
/GitHub installation token request failed with HTTP 403/,
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects an empty GitHub installation token', async () => {
|
||||
await assert.rejects(
|
||||
createInstallationToken(CONFIG, {
|
||||
execute: () => '+/8=\n',
|
||||
fetch: async () => ({
|
||||
ok: true,
|
||||
json: async () => ({ token: '' }),
|
||||
}),
|
||||
}),
|
||||
/GitHub returned an empty installation token/,
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
# Instructions for migrating from Semantic Kernel Agents to Agent Framework in .NET projects.
|
||||
# Instructions for migrating from Semantic Kernel Agents to Agent Framework in .NET projects.
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -22,13 +22,13 @@ For each project that needs to be migrated, you need to do the following:
|
||||
solution or you could not find the project, notify user and continue with other projects).
|
||||
- Identify the specific Semantic Kernel agent types being used:
|
||||
- `ChatCompletionAgent` → `ChatClientAgent`
|
||||
- `OpenAIAssistantAgent` → `assistantsClient.CreateAIAgent()` (via OpenAI Assistants client extension)
|
||||
- `AzureAIAgent` → `persistentAgentsClient.CreateAIAgent()` (via Azure AI Foundry client extension)
|
||||
- `OpenAIResponseAgent` → `responsesClient.CreateAIAgent()` (via OpenAI Responses client extension)
|
||||
- `OpenAIAssistantAgent` → `assistantsClient.AsAIAgent()` (via OpenAI Assistants client extension)
|
||||
- `AzureAIAgent` → `persistentAgentsClient.AsAIAgent()` (via Azure AI Foundry client extension)
|
||||
- `OpenAIResponseAgent` → `responsesClient.AsAIAgent()` (via OpenAI Responses client extension)
|
||||
- `A2AAgent` → `AIAgent` (via A2A card resolver)
|
||||
- `BedrockAgent` → Custom implementation required (not supported)
|
||||
- Determine if agents are being created new or retrieved from hosted services:
|
||||
- **New agents**: Use `CreateAIAgent()` methods
|
||||
- **New agents**: Use `AsAIAgent()` methods
|
||||
- **Existing hosted agents**: Use `GetAIAgent(agentId)` methods for OpenAI Assistants and Azure AI Foundry
|
||||
</agent_type_identification>
|
||||
|
||||
@@ -105,8 +105,8 @@ After completing migration, verify these specific items:
|
||||
1. **Compilation**: Execute `dotnet build` on all modified projects - zero errors required
|
||||
2. **Namespace Updates**: Confirm all `using Microsoft.SemanticKernel.Agents` statements are replaced
|
||||
3. **Method Calls**: Verify all `InvokeAsync` calls are changed to `RunAsync`
|
||||
4. **Return Types**: Confirm handling of `AgentRunResponse` instead of `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>`
|
||||
5. **Thread Creation**: Validate all thread creation uses `agent.GetNewThread()` pattern
|
||||
4. **Return Types**: Confirm handling of `AgentResponse` instead of `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>`
|
||||
5. **Thread Creation**: Validate all thread creation uses `agent.CreateSessionAsync()` pattern
|
||||
6. **Tool Registration**: Ensure `[KernelFunction]` attributes are removed and `AIFunctionFactory.Create()` is used
|
||||
7. **Options Configuration**: Verify `AgentRunOptions` or `ChatClientAgentRunOptions` replaces `AgentInvokeOptions`
|
||||
8. **Breaking Glass**: Test `RawRepresentation` access replaces `InnerContent` access
|
||||
@@ -119,8 +119,8 @@ Agent Framework provides functionality for creating and managing AI agents throu
|
||||
Key API differences:
|
||||
- Agent creation: Remove Kernel dependency, use direct client-based creation
|
||||
- Method names: `InvokeAsync` → `RunAsync`, `InvokeStreamingAsync` → `RunStreamingAsync`
|
||||
- Return types: `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>` → `AgentRunResponse`
|
||||
- Thread creation: Provider-specific constructors → `agent.GetNewThread()`
|
||||
- Return types: `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>` → `AgentResponse`
|
||||
- Thread creation: Provider-specific constructors → `agent.CreateSessionAsync()`
|
||||
- Tool registration: `KernelPlugin` system → Direct `AIFunction` registration
|
||||
- Options: `AgentInvokeOptions` → Provider-specific run options (e.g., `ChatClientAgentRunOptions`)
|
||||
</api_changes>
|
||||
@@ -142,14 +142,14 @@ Replace these Semantic Kernel agent classes with their Agent Framework equivalen
|
||||
|----------------------|----------------------------|-------------------|
|
||||
| `IChatCompletionService` | `IChatClient` | Convert to `IChatClient` using `chatService.AsChatClient()` extensions |
|
||||
| `ChatCompletionAgent` | `ChatClientAgent` | Remove `Kernel` parameter, add `IChatClient` parameter |
|
||||
| `OpenAIAssistantAgent` | `AIAgent` (via extension) | **New**: `OpenAIClient.GetAssistantClient().CreateAIAgent()` <br> **Existing**: `OpenAIClient.GetAssistantClient().GetAIAgent(assistantId)` |
|
||||
| `AzureAIAgent` | `AIAgent` (via extension) | **New**: `PersistentAgentsClient.CreateAIAgent()` <br> **Existing**: `PersistentAgentsClient.GetAIAgent(agentId)` |
|
||||
| `OpenAIResponseAgent` | `AIAgent` (via extension) | Replace with `OpenAIClient.GetOpenAIResponseClient().CreateAIAgent()` |
|
||||
| `OpenAIAssistantAgent` | `AIAgent` (via extension) | **New**: `OpenAIClient.GetAssistantClient().AsAIAgent()` <br> **Existing**: `OpenAIClient.GetAssistantClient().GetAIAgent(assistantId)` |
|
||||
| `AzureAIAgent` | `AIAgent` (via extension) | **New**: `PersistentAgentsClient.AsAIAgent()` <br> **Existing**: `PersistentAgentsClient.GetAIAgent(agentId)` |
|
||||
| `OpenAIResponseAgent` | `AIAgent` (via extension) | Replace with `OpenAIClient.GetResponsesClient().AsAIAgent()` |
|
||||
| `A2AAgent` | `AIAgent` (via extension) | Replace with `A2ACardResolver.GetAIAgentAsync()` |
|
||||
| `BedrockAgent` | Not supported | Custom implementation required |
|
||||
|
||||
**Important distinction:**
|
||||
- **CreateAIAgent()**: Use when creating new agents in the hosted service
|
||||
- **AsAIAgent()**: Use when creating new agents in the hosted service
|
||||
- **GetAIAgent(agentId)**: Use when retrieving existing agents from the hosted service
|
||||
</agent_type_identification>
|
||||
|
||||
@@ -158,16 +158,16 @@ Replace these method calls:
|
||||
|
||||
| Semantic Kernel Method | Agent Framework Method | Parameter Changes |
|
||||
|----------------------|----------------------|------------------|
|
||||
| `agent.InvokeAsync(message, thread, options)` | `agent.RunAsync(message, thread, options)` | Same parameters, different return type |
|
||||
| `agent.InvokeStreamingAsync(message, thread, options)` | `agent.RunStreamingAsync(message, thread, options)` | Same parameters, different return type |
|
||||
| `new ChatHistoryAgentThread()` | `agent.GetNewThread()` | No parameters needed |
|
||||
| `new OpenAIAssistantAgentThread(client)` | `agent.GetNewThread()` | No parameters needed |
|
||||
| `new AzureAIAgentThread(client)` | `agent.GetNewThread()` | No parameters needed |
|
||||
| `agent.InvokeAsync(message, thread, options)` | `agent.RunAsync(message, session, options)` | Same parameters, different return type |
|
||||
| `agent.InvokeStreamingAsync(message, thread, options)` | `agent.RunStreamingAsync(message, session, options)` | Same parameters, different return type |
|
||||
| `new ChatHistoryAgentThread()` | `await agent.CreateSessionAsync()` | Returns `AgentSession` |
|
||||
| `new OpenAIAssistantAgentThread(client)` | `await agent.CreateSessionAsync()` | Returns `AgentSession` |
|
||||
| `new AzureAIAgentThread(client)` | `await agent.CreateSessionAsync()` | Returns `AgentSession` |
|
||||
| `thread.DeleteAsync()` | Provider-specific cleanup | Use provider client directly |
|
||||
|
||||
Return type changes:
|
||||
- `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>` → `AgentRunResponse`
|
||||
- `IAsyncEnumerable<StreamingChatMessageContent>` → `IAsyncEnumerable<AgentRunResponseUpdate>`
|
||||
- `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>` → `AgentResponse`
|
||||
- `IAsyncEnumerable<StreamingChatMessageContent>` → `IAsyncEnumerable<AgentResponseUpdate>`
|
||||
</api_changes>
|
||||
|
||||
<configuration_changes>
|
||||
@@ -191,8 +191,8 @@ Agent Framework changes these behaviors compared to Semantic Kernel Agents:
|
||||
1. **Thread Management**: Agent Framework automatically manages thread state. Semantic Kernel required manual thread updates in some scenarios (e.g., OpenAI Responses).
|
||||
|
||||
2. **Return Types**:
|
||||
- Non-streaming: Returns single `AgentRunResponse` instead of `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>`
|
||||
- Streaming: Returns `IAsyncEnumerable<AgentRunResponseUpdate>` instead of `IAsyncEnumerable<StreamingChatMessageContent>`
|
||||
- Non-streaming: Returns single `AgentResponse` instead of `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>`
|
||||
- Streaming: Returns `IAsyncEnumerable<AgentResponseUpdate>` instead of `IAsyncEnumerable<StreamingChatMessageContent>`
|
||||
|
||||
3. **Tool Registration**: Agent Framework uses direct function registration without requiring `[KernelFunction]` attributes.
|
||||
|
||||
@@ -222,6 +222,8 @@ using Microsoft.Extensions.AI;
|
||||
using Microsoft.Agents.AI;
|
||||
// Provider-specific namespaces (add only if needed):
|
||||
using OpenAI; // For OpenAI provider
|
||||
using OpenAI.Chat; // For ChatClient.AsAIAgent() extension
|
||||
using OpenAI.Responses; // For ResponsesClient.AsAIAgent() extension
|
||||
using Azure.AI.OpenAI; // For Azure OpenAI provider
|
||||
using Azure.AI.Agents.Persistent; // For Azure AI Foundry provider
|
||||
using Azure.Identity; // For Azure authentication
|
||||
@@ -254,7 +256,7 @@ AIAgent agent = new ChatClientAgent(chatClient, instructions: "You are a helpful
|
||||
// Method 2: Extension method (recommended)
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetChatClient(modelId)
|
||||
.CreateAIAgent(instructions: "You are a helpful assistant");
|
||||
.AsAIAgent(instructions: "You are a helpful assistant");
|
||||
```
|
||||
</configuration_changes>
|
||||
|
||||
@@ -314,7 +316,7 @@ AIAgent agent = new ChatClientAgent(chatClient, instructions: "You are a helpful
|
||||
// Method 2: Extension method (recommended)
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetChatClient(modelId)
|
||||
.CreateAIAgent(instructions: "You are a helpful assistant");
|
||||
.AsAIAgent(instructions: "You are a helpful assistant");
|
||||
```
|
||||
|
||||
**Required changes:**
|
||||
@@ -338,12 +340,12 @@ AgentThread thread = new AzureAIAgentThread(azureClient);
|
||||
**With this unified Agent Framework pattern:**
|
||||
```csharp
|
||||
// Use this single pattern for all agent types:
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
```
|
||||
|
||||
**Required changes:**
|
||||
1. Remove all `new [Provider]AgentThread()` constructor calls
|
||||
2. Replace with `agent.GetNewThread()` method call
|
||||
2. Replace with `agent.CreateSessionAsync()` method call
|
||||
3. Remove provider client parameters from thread creation
|
||||
4. Use the same pattern regardless of agent provider type
|
||||
</api_changes>
|
||||
@@ -369,7 +371,7 @@ ChatCompletionAgent agent = new() { Kernel = kernel };
|
||||
[Description("Get the weather for a location")] // Keep Description attribute
|
||||
static string GetWeather(string location) => $"Weather in {location}";
|
||||
|
||||
AIAgent agent = chatClient.CreateAIAgent(
|
||||
AIAgent agent = chatClient.AsAIAgent(
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
```
|
||||
@@ -415,12 +417,12 @@ await foreach (var item in agent.InvokeAsync(userInput, thread)) { ... }
|
||||
static string GetWeather(string location) => $"Weather in {location}";
|
||||
|
||||
// Start with an existing agent
|
||||
AIAgent existingAgent = chatClient.CreateAIAgent(
|
||||
AIAgent existingAgent = chatClient.AsAIAgent(
|
||||
instructions: "You are a helpful assistant");
|
||||
|
||||
// Create an augmented agent with additional tools using builder middleware
|
||||
var augmentedAgent = existingAgent.AsBuilder()
|
||||
.Use(async (chatMessages, agentThread, agentRunOptions, next, cancellationToken) =>
|
||||
.Use(async (chatMessages, agentSession, agentRunOptions, next, cancellationToken) =>
|
||||
{
|
||||
if (agentRunOptions is ChatClientAgentRunOptions chatClientAgentRunOptions)
|
||||
{
|
||||
@@ -429,12 +431,12 @@ var augmentedAgent = existingAgent.AsBuilder()
|
||||
chatClientAgentRunOptions.ChatOptions.Tools.Add(AIFunctionFactory.Create(GetWeather));
|
||||
}
|
||||
|
||||
return await next(chatMessages, agentThread, agentRunOptions, cancellationToken);
|
||||
return await next(chatMessages, agentSession, agentRunOptions, cancellationToken);
|
||||
})
|
||||
.Build();
|
||||
|
||||
// Use the augmented agent with the additional tools
|
||||
AgentRunResponse result = await augmentedAgent.RunAsync(userInput, thread);
|
||||
AgentResponse result = await augmentedAgent.RunAsync(userInput, session);
|
||||
```
|
||||
|
||||
**Required changes:**
|
||||
@@ -464,7 +466,7 @@ await foreach (AgentResponseItem<ChatMessageContent> item in agent.InvokeAsync(u
|
||||
|
||||
**With this Agent Framework non-streaming pattern:**
|
||||
```csharp
|
||||
AgentRunResponse result = await agent.RunAsync(userInput, thread, options);
|
||||
AgentResponse result = await agent.RunAsync(userInput, session, options);
|
||||
Console.WriteLine(result);
|
||||
```
|
||||
|
||||
@@ -478,7 +480,7 @@ await foreach (StreamingChatMessageContent update in agent.InvokeStreamingAsync(
|
||||
|
||||
**With this Agent Framework streaming pattern:**
|
||||
```csharp
|
||||
await foreach (AgentRunResponseUpdate update in agent.RunStreamingAsync(userInput, thread, options))
|
||||
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(userInput, session, options))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
@@ -487,8 +489,8 @@ await foreach (AgentRunResponseUpdate update in agent.RunStreamingAsync(userInpu
|
||||
**Required changes:**
|
||||
1. Replace `agent.InvokeAsync()` with `agent.RunAsync()`
|
||||
2. Replace `agent.InvokeStreamingAsync()` with `agent.RunStreamingAsync()`
|
||||
3. Change return type handling from `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>` to `AgentRunResponse`
|
||||
4. Change streaming type from `StreamingChatMessageContent` to `AgentRunResponseUpdate`
|
||||
3. Change return type handling from `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>` to `AgentResponse`
|
||||
4. Change streaming type from `StreamingChatMessageContent` to `AgentResponseUpdate`
|
||||
5. Remove `await foreach` for non-streaming calls
|
||||
6. Access message content directly from result object instead of iterating
|
||||
</api_changes>
|
||||
@@ -537,7 +539,7 @@ services.AddTransient<ChatCompletionAgent>(sp => new()
|
||||
services.AddTransient<AIAgent>(sp =>
|
||||
new OpenAIClient(apiKey)
|
||||
.GetChatClient(modelId)
|
||||
.CreateAIAgent(instructions: "You are helpful"));
|
||||
.AsAIAgent(instructions: "You are helpful"));
|
||||
```
|
||||
|
||||
**Required changes:**
|
||||
@@ -564,11 +566,11 @@ For every thread created if there's intent to cleanup, the caller should track a
|
||||
```csharp
|
||||
// For OpenAI Assistants (when cleanup is needed):
|
||||
var assistantClient = new OpenAIClient(apiKey).GetAssistantClient();
|
||||
await assistantClient.DeleteThreadAsync(thread.ConversationId);
|
||||
await assistantClient.DeleteThreadAsync(session.ConversationId);
|
||||
|
||||
// For Azure AI Foundry (when cleanup is needed):
|
||||
var persistentClient = new PersistentAgentsClient(endpoint, credential);
|
||||
await persistentClient.Threads.DeleteThreadAsync(thread.ConversationId);
|
||||
await persistentClient.Threads.DeleteThreadAsync(session.ConversationId);
|
||||
|
||||
// No thread and agent cleanup is needed for non-hosted agent providers like
|
||||
// - Azure OpenAI Chat Completion
|
||||
@@ -580,7 +582,7 @@ await persistentClient.Threads.DeleteThreadAsync(thread.ConversationId);
|
||||
**Required changes:**
|
||||
1. Remove `thread.DeleteAsync()` calls
|
||||
2. Use provider-specific client for cleanup when required
|
||||
3. Access thread ID via `thread.ConversationId` property
|
||||
3. Access thread ID via `session.ConversationId` property
|
||||
4. Only implement cleanup for providers that require it (Assistants, Azure AI Foundry)
|
||||
</api_changes>
|
||||
|
||||
@@ -593,14 +595,14 @@ Use these exact patterns for each provider:
|
||||
```csharp
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetChatClient(modelId)
|
||||
.CreateAIAgent(instructions: instructions);
|
||||
.AsAIAgent(instructions: instructions);
|
||||
```
|
||||
|
||||
**OpenAI Assistants (New):**
|
||||
```csharp
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetAssistantClient()
|
||||
.CreateAIAgent(modelId, instructions: instructions);
|
||||
.AsAIAgent(modelId, instructions: instructions);
|
||||
```
|
||||
|
||||
**OpenAI Assistants (Existing):**
|
||||
@@ -614,13 +616,13 @@ AIAgent agent = new OpenAIClient(apiKey)
|
||||
```csharp
|
||||
AIAgent agent = new AzureOpenAIClient(endpoint, credential)
|
||||
.GetChatClient(deploymentName)
|
||||
.CreateAIAgent(instructions: instructions);
|
||||
.AsAIAgent(instructions: instructions);
|
||||
```
|
||||
|
||||
**Azure AI Foundry (New):**
|
||||
```csharp
|
||||
AIAgent agent = new PersistentAgentsClient(endpoint, credential)
|
||||
.CreateAIAgent(model: deploymentName, instructions: instructions);
|
||||
.AsAIAgent(model: deploymentName, instructions: instructions);
|
||||
```
|
||||
|
||||
**Azure AI Foundry (Existing):**
|
||||
@@ -665,9 +667,9 @@ using OpenAI;
|
||||
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetChatClient(modelId)
|
||||
.CreateAIAgent(instructions: "You are helpful");
|
||||
.AsAIAgent(instructions: "You are helpful");
|
||||
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
```
|
||||
</configuration_changes>
|
||||
|
||||
@@ -691,7 +693,7 @@ kernel.Plugins.Add(plugin);
|
||||
static string GetWeather([Description("Location")] string location)
|
||||
=> $"Weather in {location}";
|
||||
|
||||
AIAgent agent = chatClient.CreateAIAgent(
|
||||
AIAgent agent = chatClient.AsAIAgent(
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
```
|
||||
@@ -714,7 +716,7 @@ await foreach (var result in agent.InvokeAsync(input, thread, options))
|
||||
```csharp
|
||||
ChatClientAgentRunOptions options = new(new ChatOptions { MaxOutputTokens = 1000 });
|
||||
|
||||
AgentRunResponse result = await agent.RunAsync(input, thread, options);
|
||||
AgentResponse result = await agent.RunAsync(input, session, options);
|
||||
Console.WriteLine(result);
|
||||
|
||||
// Access underlying content when needed:
|
||||
@@ -742,7 +744,7 @@ await foreach (var result in agent.InvokeAsync(input, thread, options))
|
||||
|
||||
**With this Agent Framework non-streaming usage pattern:**
|
||||
```csharp
|
||||
AgentRunResponse result = await agent.RunAsync(input, thread, options);
|
||||
AgentResponse result = await agent.RunAsync(input, session, options);
|
||||
Console.WriteLine($"Tokens: {result.Usage.TotalTokenCount}");
|
||||
```
|
||||
|
||||
@@ -762,7 +764,7 @@ await foreach (StreamingChatMessageContent response in agent.InvokeStreamingAsyn
|
||||
|
||||
**With this Agent Framework streaming usage pattern:**
|
||||
```csharp
|
||||
await foreach (AgentRunResponseUpdate update in agent.RunStreamingAsync(input, thread, options))
|
||||
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(input, session, options))
|
||||
{
|
||||
if (update.Contents.OfType<UsageContent>().FirstOrDefault() is { } usageContent)
|
||||
{
|
||||
@@ -787,7 +789,7 @@ await foreach (var content in agent.InvokeAsync(userInput, thread))
|
||||
|
||||
**With this Agent Framework breaking glass pattern:**
|
||||
```csharp
|
||||
var agentRunResponse = await agent.RunAsync(userInput, thread);
|
||||
var agentRunResponse = await agent.RunAsync(userInput, session);
|
||||
|
||||
// If the agent uses a ChatClient the first breaking glass probably will be a Microsoft.Extensions.AI.ChatResponse
|
||||
ChatResponse? chatResponse = agentRunResponse.RawRepresentation as ChatResponse;
|
||||
@@ -829,7 +831,7 @@ await foreach (var content in agent.InvokeAsync(userInput, thread))
|
||||
|
||||
**With this Agent Framework CodeInterpreter pattern:**
|
||||
```csharp
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
var result = await agent.RunAsync(userInput, session);
|
||||
Console.WriteLine(result);
|
||||
|
||||
// Extract chat response MEAI type via first level breaking glass
|
||||
@@ -919,7 +921,7 @@ var openAIResponse = chatCompletion.GetRawResponse();
|
||||
|
||||
**Issue: Thread Type Mismatches**
|
||||
- **Problem**: Provider-specific thread constructors not found
|
||||
- **Solution**: Replace all thread constructors with `agent.GetNewThread()`
|
||||
- **Solution**: Replace all thread constructors with `agent.CreateSessionAsync()`
|
||||
|
||||
**Issue: Options Configuration**
|
||||
- **Problem**: `AgentInvokeOptions` type not found
|
||||
@@ -937,7 +939,7 @@ var openAIResponse = chatCompletion.GetRawResponse();
|
||||
2. **Update Namespaces**: Replace SK namespaces with AF namespaces
|
||||
3. **Update Agent Creation**: Remove Kernel, use direct client creation
|
||||
4. **Update Method Calls**: Replace `InvokeAsync` with `RunAsync`
|
||||
5. **Update Thread Creation**: Replace provider-specific constructors with `GetNewThread()`
|
||||
5. **Update Thread Creation**: Replace provider-specific constructors with `await agent.CreateSessionAsync()`
|
||||
6. **Update Tool Registration**: Remove attributes, use `AIFunctionFactory.Create()`
|
||||
7. **Update Options**: Replace `AgentInvokeOptions` with provider-specific options
|
||||
8. **Test and Validate**: Compile and test all functionality
|
||||
@@ -988,9 +990,9 @@ using OpenAI;
|
||||
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetChatClient(modelId)
|
||||
.CreateAIAgent(instructions: "You are a helpful assistant");
|
||||
.AsAIAgent(instructions: "You are a helpful assistant");
|
||||
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
```
|
||||
|
||||
### 2. Azure OpenAI Chat Completion Migration
|
||||
@@ -1038,7 +1040,7 @@ using Azure.Identity;
|
||||
|
||||
AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.CreateAIAgent(instructions: "You are a helpful assistant");
|
||||
.AsAIAgent(instructions: "You are a helpful assistant");
|
||||
```
|
||||
|
||||
### 3. OpenAI Assistants Migration
|
||||
@@ -1083,12 +1085,12 @@ using OpenAI;
|
||||
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetAssistantClient()
|
||||
.CreateAIAgent(modelId, instructions: "You are a helpful assistant");
|
||||
.AsAIAgent(modelId, instructions: "You are a helpful assistant");
|
||||
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
|
||||
// Cleanup when needed
|
||||
await assistantClient.DeleteThreadAsync(thread.ConversationId);
|
||||
await assistantClient.DeleteThreadAsync(session.ConversationId);
|
||||
```
|
||||
|
||||
**Retrieving an existing assistant:**
|
||||
@@ -1100,7 +1102,7 @@ AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetAssistantClient()
|
||||
.GetAIAgent(assistantId); // Use existing assistant ID
|
||||
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
```
|
||||
</api_changes>
|
||||
|
||||
@@ -1163,12 +1165,12 @@ using Azure.Identity;
|
||||
var client = new PersistentAgentsClient(endpoint, new AzureCliCredential());
|
||||
|
||||
// Create a new AIAgent using Agent Framework
|
||||
AIAgent agent = client.CreateAIAgent(
|
||||
AIAgent agent = client.AsAIAgent(
|
||||
model: deploymentName,
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [/* List of specialized Azure.AI.Agents.Persistent.ToolDefinition types */]);
|
||||
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
```
|
||||
|
||||
**Retrieving an existing agent:**
|
||||
@@ -1182,7 +1184,7 @@ var client = new PersistentAgentsClient(endpoint, new AzureCliCredential());
|
||||
// Retrieve an existing AIAgent using its ID
|
||||
AIAgent agent = await client.GetAIAgentAsync(agentId);
|
||||
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
```
|
||||
</api_changes>
|
||||
|
||||
@@ -1269,20 +1271,21 @@ await foreach (AgentResponseItem<ChatMessageContent> responseItem in responseIte
|
||||
Agent Framework automatically manages the thread, so there's no need to manually update it.
|
||||
|
||||
```csharp
|
||||
using Microsoft.Agents.AI.OpenAI;
|
||||
using OpenAI.Chat; // For ChatClient.AsAIAgent()
|
||||
using OpenAI.Responses; // For ResponsesClient.AsAIAgent()
|
||||
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetOpenAIResponseClient(modelId)
|
||||
.CreateAIAgent(
|
||||
.GetResponsesClient(modelId)
|
||||
.AsAIAgent(
|
||||
name: "ResponseAgent",
|
||||
instructions: "Answer all queries in English and French.",
|
||||
tools: [/* AITools */]);
|
||||
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
var result = await agent.RunAsync(userInput, session);
|
||||
|
||||
// The thread will be automatically updated with the new response id from this point
|
||||
// The session will be automatically updated with the new response id from this point
|
||||
```
|
||||
</api_changes>
|
||||
|
||||
@@ -1336,21 +1339,22 @@ await foreach (AgentResponseItem<ChatMessageContent> responseItem in responseIte
|
||||
Agent Framework automatically manages the thread, so there's no need to manually update it.
|
||||
|
||||
```csharp
|
||||
using Microsoft.Agents.AI.OpenAI;
|
||||
using OpenAI.Chat; // For ChatClient.AsAIAgent()
|
||||
using OpenAI.Responses; // For ResponsesClient.AsAIAgent()
|
||||
using Azure.AI.OpenAI;
|
||||
|
||||
AIAgent agent = new AzureOpenAIClient(endpoint, new AzureCliCredential())
|
||||
.GetOpenAIResponseClient(modelId)
|
||||
.CreateAIAgent(
|
||||
.GetResponsesClient(modelId)
|
||||
.AsAIAgent(
|
||||
name: "ResponseAgent",
|
||||
instructions: "Answer all queries in English and French.",
|
||||
tools: [/* AITools */]);
|
||||
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
var result = await agent.RunAsync(userInput, session);
|
||||
|
||||
// The thread will be automatically updated with the new response id from this point
|
||||
// The session will be automatically updated with the new response id from this point
|
||||
```
|
||||
</api_changes>
|
||||
|
||||
@@ -1513,7 +1517,7 @@ AITool[] tools =
|
||||
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetChatClient(modelId)
|
||||
.CreateAIAgent(
|
||||
.AsAIAgent(
|
||||
instructions: "You are a weather assistant",
|
||||
tools: tools);
|
||||
```
|
||||
@@ -1562,10 +1566,10 @@ var renderedTemplate = await new KernelPromptTemplateFactory()
|
||||
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetChatClient(modelId)
|
||||
.CreateAIAgent(instructions: renderedTemplate);
|
||||
.AsAIAgent(instructions: renderedTemplate);
|
||||
|
||||
// No template variables in invocation - use plain string
|
||||
var result = await agent.RunAsync("What's the weather?", thread);
|
||||
var result = await agent.RunAsync("What's the weather?");
|
||||
Console.WriteLine(result);
|
||||
```
|
||||
</behavioral_changes>
|
||||
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/stale@v5
|
||||
- uses: actions/stale@1e223db275d687790206a7acac4d1a11bd6fe629 # v10.4.0
|
||||
with:
|
||||
days-before-issue-stale: 90
|
||||
days-before-issue-close: 14
|
||||
|
||||
@@ -32,13 +32,13 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
uses: github/codeql-action/init@f3712979fa5f215279b101dd0a2e3bdfb4353324 # v3.37.7
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
if: ${{ matrix.language != 'java' }}
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
uses: github/codeql-action/autobuild@f3712979fa5f215279b101dd0a2e3bdfb4353324 # v3.37.7
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
@@ -65,6 +65,6 @@ jobs:
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
uses: github/codeql-action/analyze@f3712979fa5f215279b101dd0a2e3bdfb4353324 # v3.37.7
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
@@ -15,8 +15,8 @@ on:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
copilot-requests: write
|
||||
id-token: write
|
||||
|
||||
concurrency:
|
||||
group: devflow-pr-review-${{ github.repository }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
@@ -27,14 +27,40 @@ env:
|
||||
DEVFLOW_REF: main
|
||||
TARGET_REPO_PATH: ${{ github.workspace }}/target-repo
|
||||
DEVFLOW_PATH: ${{ github.workspace }}/devflow
|
||||
MODEL_CONFIG_PATH: ${{ github.workspace }}/devflow/config.ci.yaml
|
||||
|
||||
jobs:
|
||||
review:
|
||||
runs-on: ubuntu-latest
|
||||
environment: github-app-auth
|
||||
timeout-minutes: 60
|
||||
if: ${{ github.event_name != 'pull_request_target' || !github.event.pull_request.draft }}
|
||||
|
||||
steps:
|
||||
- name: Checkout GitHub automation
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.base.sha || github.sha }}
|
||||
sparse-checkout: .github/actions/github-app-token
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
|
||||
- name: Get GitHub automation token
|
||||
id: github-auth
|
||||
uses: ./.github/actions/github-app-token
|
||||
with:
|
||||
mode: ${{ vars.GH_APP_AUTH_MODE }}
|
||||
azure-client-id: ${{ secrets.GH_APP_AZURE_CLIENT_ID }}
|
||||
azure-tenant-id: ${{ secrets.GH_APP_AZURE_TENANT_ID }}
|
||||
azure-subscription-id: ${{ secrets.GH_APP_AZURE_SUBSCRIPTION_ID }}
|
||||
key-vault-name: ${{ secrets.GH_APP_KEY_VAULT_NAME }}
|
||||
key-name: ${{ secrets.GH_APP_KEY_NAME }}
|
||||
github-app-client-id: ${{ secrets.GH_APP_CLIENT_ID }}
|
||||
github-app-installation-id: ${{ secrets.GH_APP_INSTALLATION_ID }}
|
||||
repository: ${{ github.repository }}
|
||||
permission-profile: devflow
|
||||
fallback-token: ${{ secrets.GH_ACTIONS_PR_WRITE }}
|
||||
|
||||
- name: Resolve PR metadata
|
||||
id: pr
|
||||
shell: bash
|
||||
@@ -64,7 +90,7 @@ jobs:
|
||||
|
||||
# Safe checkout: base repo only, not the untrusted PR head.
|
||||
- name: Checkout target repo base
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.base.sha || github.sha }}
|
||||
fetch-depth: 0
|
||||
@@ -73,7 +99,7 @@ jobs:
|
||||
|
||||
# Private DevFlow checkout: the PAT/token grants access to this repo's code.
|
||||
- name: Checkout DevFlow
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
repository: ${{ env.DEVFLOW_REPOSITORY }}
|
||||
ref: ${{ env.DEVFLOW_REF }}
|
||||
@@ -83,12 +109,12 @@ jobs:
|
||||
path: devflow
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
||||
with:
|
||||
python-version: "3.13"
|
||||
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
|
||||
with:
|
||||
version: "0.5.x"
|
||||
enable-cache: true
|
||||
@@ -101,8 +127,8 @@ jobs:
|
||||
id: spam
|
||||
working-directory: ${{ env.DEVFLOW_PATH }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GH_COPILOT_TOKEN: ${{ secrets.GH_COPILOT_TOKEN }}
|
||||
DEVFLOW_GITHUB_TOKEN: ${{ steps.github-auth.outputs.token }}
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
SK_REPO_PATH: ${{ env.TARGET_REPO_PATH }}
|
||||
AGENT_REPO_PATH: ${{ env.TARGET_REPO_PATH }}
|
||||
PR_REPO: ${{ steps.pr.outputs.repo }}
|
||||
@@ -112,6 +138,7 @@ jobs:
|
||||
--repo "$PR_REPO" \
|
||||
--pr-number "$PR_NUMBER" \
|
||||
--repo-path "${TARGET_REPO_PATH}" \
|
||||
--github-token "$DEVFLOW_GITHUB_TOKEN" \
|
||||
--apply-labels
|
||||
|
||||
- name: Stop after spam gate
|
||||
@@ -127,8 +154,8 @@ jobs:
|
||||
id: review
|
||||
working-directory: ${{ env.DEVFLOW_PATH }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GH_COPILOT_TOKEN: ${{ secrets.GH_COPILOT_TOKEN }}
|
||||
DEVFLOW_GITHUB_TOKEN: ${{ steps.github-auth.outputs.token }}
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
SK_REPO_PATH: ${{ env.TARGET_REPO_PATH }}
|
||||
AGENT_REPO_PATH: ${{ env.TARGET_REPO_PATH }}
|
||||
PR_URL: ${{ steps.pr.outputs.pr_url }}
|
||||
@@ -136,4 +163,5 @@ jobs:
|
||||
uv run python scripts/trigger_pr_review.py \
|
||||
--pr-url "$PR_URL" \
|
||||
--github-username "$GITHUB_ACTOR" \
|
||||
--github-token "$DEVFLOW_GITHUB_TOKEN" \
|
||||
--no-require-comment-selection
|
||||
|
||||
@@ -29,10 +29,10 @@ jobs:
|
||||
outputs:
|
||||
dotnetChanges: ${{ steps.filter.outputs.dotnet }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: dorny/paths-filter@v2
|
||||
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
|
||||
id: filter
|
||||
with:
|
||||
filters: |
|
||||
@@ -69,19 +69,19 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
environment: ${{ matrix.environment }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup dotnet
|
||||
uses: actions/setup-dotnet@v5
|
||||
uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5.4.0
|
||||
with:
|
||||
global-json-file: ${{ github.workspace }}/dotnet/global.json
|
||||
|
||||
- name: Build dotnet solutions
|
||||
shell: bash
|
||||
run: |
|
||||
export SOLUTIONS=$(find ./dotnet/ -type f -name "*.slnx" | tr '\n' ' ')
|
||||
export SOLUTIONS=$(find ./dotnet/ -type f -name "*.slnx" | grep -v "MEVD.slnx" | tr '\n' ' ')
|
||||
for solution in $SOLUTIONS; do
|
||||
dotnet build $solution -c ${{ matrix.configuration }} --warnaserror
|
||||
done
|
||||
@@ -89,7 +89,7 @@ jobs:
|
||||
- name: Package install check
|
||||
shell: bash
|
||||
run: |
|
||||
export SOLUTIONS=$(find ./dotnet/ -type f -name "*.slnx" | tr '\n' ' ')
|
||||
export SOLUTIONS=$(find ./dotnet/ -type f -name "*.slnx" | grep -v "MEVD.slnx" | tr '\n' ' ')
|
||||
for solution in $SOLUTIONS; do
|
||||
dotnet pack $solution -c ${{ matrix.configuration }} --no-build --no-restore --output ./artifacts
|
||||
done
|
||||
@@ -115,7 +115,7 @@ jobs:
|
||||
- name: Run Unit Tests
|
||||
shell: bash
|
||||
run: |
|
||||
export UT_PROJECTS=$(find ./dotnet -type f -name "*.UnitTests.csproj" | grep -v -E "(Experimental.Orchestration.Flow.UnitTests.csproj|Experimental.Assistants.UnitTests.csproj)" | tr '\n' ' ')
|
||||
export UT_PROJECTS=$(find ./dotnet -type f -name "*.UnitTests.csproj" | grep -v -E "(Experimental.Orchestration.Flow.UnitTests.csproj|Experimental.Assistants.UnitTests.csproj)" | grep -v "test/VectorData/" | tr '\n' ' ')
|
||||
for project in $UT_PROJECTS; do
|
||||
dotnet test -c ${{ matrix.configuration }} $project --no-build -v Normal --logger trx --collect:"XPlat Code Coverage" --results-directory:"TestResults/Coverage/" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.ExcludeByAttribute=GeneratedCodeAttribute,CompilerGeneratedAttribute,ExcludeFromCodeCoverageAttribute
|
||||
done
|
||||
@@ -126,7 +126,7 @@ jobs:
|
||||
|
||||
- name: Azure CLI Login
|
||||
if: github.event_name != 'pull_request' && matrix.integration-tests
|
||||
uses: azure/login@v2
|
||||
uses: azure/login@7184910d9eb2b1c5e48f7073824a90609bb9b6d6 # v2.3.1
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
@@ -184,14 +184,14 @@ jobs:
|
||||
|
||||
# Generate test reports and check coverage
|
||||
- name: Generate test reports
|
||||
uses: danielpalme/[email protected]2
|
||||
uses: danielpalme/ReportGenerator-GitHub-Action@18e0cd4c1bebd0c8b3978b380a6a4ea61c51178e # 5.4.15
|
||||
with:
|
||||
reports: "./TestResults/Coverage/**/coverage.cobertura.xml"
|
||||
targetdir: "./TestResults/Reports"
|
||||
reporttypes: "HtmlInline;JsonSummary"
|
||||
|
||||
- name: Upload coverage report artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: CoverageReport-${{ matrix.os }}-${{ matrix.dotnet }}-${{ matrix.configuration }} # Artifact name
|
||||
path: ./TestResults/Reports # Directory containing files to upload
|
||||
@@ -232,13 +232,13 @@ jobs:
|
||||
- name: Fail workflow if tests failed
|
||||
id: check_tests_failed
|
||||
if: contains(join(needs.*.result, ','), 'failure')
|
||||
uses: actions/github-script@v6
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
with:
|
||||
script: core.setFailed('Integration Tests Failed!')
|
||||
|
||||
- name: Fail workflow if tests cancelled
|
||||
id: check_tests_cancelled
|
||||
if: contains(join(needs.*.result, ','), 'cancelled')
|
||||
uses: actions/github-script@v6
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
with:
|
||||
script: core.setFailed('Integration Tests Cancelled!')
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
clean: true
|
||||
persist-credentials: false
|
||||
@@ -55,7 +55,7 @@ jobs:
|
||||
done
|
||||
|
||||
- name: Upload dotnet test results
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: dotnet-testresults-${{ matrix.configuration }}
|
||||
path: ./TestResults
|
||||
@@ -72,19 +72,19 @@ jobs:
|
||||
env:
|
||||
NUGET_CERT_REVOCATION_MODE: offline
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
clean: true
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup .NET SDK ${{ matrix.dotnet-version }}
|
||||
uses: actions/setup-dotnet@v5
|
||||
uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5.4.0
|
||||
with:
|
||||
dotnet-version: ${{ matrix.dotnet-version }}
|
||||
env:
|
||||
NUGET_AUTH_TOKEN: ${{ secrets.GPR_READ_TOKEN }}
|
||||
|
||||
- uses: actions/cache@v4
|
||||
- uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
# Look to see if there is a cache hit for the corresponding requirements file
|
||||
@@ -122,7 +122,7 @@ jobs:
|
||||
done
|
||||
|
||||
- name: Upload dotnet test results
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: dotnet-testresults-${{ matrix.configuration }}
|
||||
path: ./TestResults
|
||||
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: jitterbit/get-changed-files@v1
|
||||
uses: jitterbit/get-changed-files@b17fbb00bdc0c0f63fcf166580804b4d2cdc2a42 # v1
|
||||
continue-on-error: true
|
||||
|
||||
- name: No C# files changed
|
||||
@@ -53,11 +53,14 @@ jobs:
|
||||
- name: Find csproj files
|
||||
id: find-csproj
|
||||
if: github.event_name != 'pull_request' || steps.changed-files.outputs.added_modified != '' || steps.changed-files.outcome == 'failure'
|
||||
env:
|
||||
ADDED_MODIFIED: ${{ steps.changed-files.outputs.added_modified }}
|
||||
run: |
|
||||
csproj_files=()
|
||||
exclude_files=("Experimental.Orchestration.Flow.csproj" "Experimental.Orchestration.Flow.UnitTests.csproj" "Experimental.Orchestration.Flow.IntegrationTests.csproj")
|
||||
set -f
|
||||
if [[ ${{ steps.changed-files.outcome }} == 'success' ]]; then
|
||||
for file in ${{ steps.changed-files.outputs.added_modified }}; do
|
||||
for file in $ADDED_MODIFIED; do
|
||||
echo "$file was changed"
|
||||
dir="./$file"
|
||||
while [[ $dir != "." && $dir != "/" && $dir != $GITHUB_WORKSPACE ]]; do
|
||||
@@ -78,7 +81,8 @@ jobs:
|
||||
fi
|
||||
csproj_files=($(printf "%s\n" "${csproj_files[@]}" | sort -u))
|
||||
echo "Found ${#csproj_files[@]} unique csproj/slnx files: ${csproj_files[*]}"
|
||||
echo "::set-output name=csproj_files::${csproj_files[*]}"
|
||||
echo "csproj_files=${csproj_files[*]}" >> "$GITHUB_OUTPUT"
|
||||
set +f
|
||||
|
||||
- name: Pull container dotnet/sdk:${{ matrix.dotnet }}
|
||||
if: steps.find-csproj.outputs.csproj_files != ''
|
||||
@@ -87,8 +91,11 @@ jobs:
|
||||
# This step will run dotnet format on each of the unique csproj files and fail if any changes are made
|
||||
- name: Run dotnet format
|
||||
if: steps.find-csproj.outputs.csproj_files != ''
|
||||
env:
|
||||
CSPROJ_FILES: ${{ steps.find-csproj.outputs.csproj_files }}
|
||||
run: |
|
||||
for csproj in ${{ steps.find-csproj.outputs.csproj_files }}; do
|
||||
set -f
|
||||
for csproj in $CSPROJ_FILES; do
|
||||
echo "Running dotnet format on $csproj"
|
||||
docker run --rm -v $(pwd):/app -w /app mcr.microsoft.com/dotnet/sdk:${{ matrix.dotnet }} /bin/sh -c "dotnet format $csproj --verify-no-changes --verbosity diagnostic"
|
||||
docker run --rm -v "$(pwd):/app" -w /app mcr.microsoft.com/dotnet/sdk:${{ matrix.dotnet }} dotnet format "$csproj" --verify-no-changes --verbosity diagnostic
|
||||
done
|
||||
|
||||
@@ -22,14 +22,14 @@ jobs:
|
||||
configuration: [Debug]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
with:
|
||||
clean: true
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v5
|
||||
uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5.4.0
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
with:
|
||||
dotnet-version: 10.0.x
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
done
|
||||
|
||||
- name: Upload dotnet test results
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: dotnet-testresults-${{ matrix.configuration }}
|
||||
path: ./TestResults
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
name: GitHub automation tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/actions/**"
|
||||
- ".github/tests/**"
|
||||
- ".github/workflows/devflow-pr-review.yml"
|
||||
- ".github/workflows/github-automation-tests.yml"
|
||||
- ".github/workflows/label-issues.yml"
|
||||
- ".github/workflows/label-pr.yml"
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- ".github/actions/**"
|
||||
- ".github/tests/**"
|
||||
- ".github/workflows/devflow-pr-review.yml"
|
||||
- ".github/workflows/github-automation-tests.yml"
|
||||
- ".github/workflows/label-issues.yml"
|
||||
- ".github/workflows/label-pr.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
with:
|
||||
node-version: "22"
|
||||
|
||||
- name: Run JavaScript tests
|
||||
run: node --test .github/tests/*.js
|
||||
@@ -10,12 +10,37 @@ jobs:
|
||||
name: "Issue: add labels"
|
||||
if: ${{ github.event.action == 'opened' || github.event.action == 'reopened' }}
|
||||
runs-on: ubuntu-latest
|
||||
environment: github-app-auth
|
||||
permissions:
|
||||
issues: write
|
||||
contents: read
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/github-script@v6
|
||||
- name: Checkout GitHub automation
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
github-token: ${{ secrets.GH_ACTIONS_PR_WRITE }}
|
||||
sparse-checkout: .github/actions/github-app-token
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
|
||||
- name: Get GitHub automation token
|
||||
id: github-auth
|
||||
uses: ./.github/actions/github-app-token
|
||||
with:
|
||||
mode: ${{ vars.GH_APP_AUTH_MODE }}
|
||||
azure-client-id: ${{ secrets.GH_APP_AZURE_CLIENT_ID }}
|
||||
azure-tenant-id: ${{ secrets.GH_APP_AZURE_TENANT_ID }}
|
||||
azure-subscription-id: ${{ secrets.GH_APP_AZURE_SUBSCRIPTION_ID }}
|
||||
key-vault-name: ${{ secrets.GH_APP_KEY_VAULT_NAME }}
|
||||
key-name: ${{ secrets.GH_APP_KEY_NAME }}
|
||||
github-app-client-id: ${{ secrets.GH_APP_CLIENT_ID }}
|
||||
github-app-installation-id: ${{ secrets.GH_APP_INSTALLATION_ID }}
|
||||
repository: ${{ github.repository }}
|
||||
permission-profile: issues
|
||||
fallback-token: ${{ secrets.GH_ACTIONS_PR_WRITE }}
|
||||
|
||||
- uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
with:
|
||||
github-token: ${{ steps.github-auth.outputs.token }}
|
||||
script: |
|
||||
// Get the issue body and title
|
||||
const body = context.payload.issue.body
|
||||
|
||||
@@ -11,11 +11,36 @@ on: [pull_request_target]
|
||||
jobs:
|
||||
add_label:
|
||||
runs-on: ubuntu-latest
|
||||
environment: github-app-auth
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- uses: actions/labeler@v4
|
||||
- name: Checkout GitHub automation
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
repo-token: "${{ secrets.GH_ACTIONS_PR_WRITE }}"
|
||||
ref: ${{ github.event.pull_request.base.sha }}
|
||||
sparse-checkout: .github/actions/github-app-token
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
|
||||
- name: Get GitHub automation token
|
||||
id: github-auth
|
||||
uses: ./.github/actions/github-app-token
|
||||
with:
|
||||
mode: ${{ vars.GH_APP_AUTH_MODE }}
|
||||
azure-client-id: ${{ secrets.GH_APP_AZURE_CLIENT_ID }}
|
||||
azure-tenant-id: ${{ secrets.GH_APP_AZURE_TENANT_ID }}
|
||||
azure-subscription-id: ${{ secrets.GH_APP_AZURE_SUBSCRIPTION_ID }}
|
||||
key-vault-name: ${{ secrets.GH_APP_KEY_VAULT_NAME }}
|
||||
key-name: ${{ secrets.GH_APP_KEY_NAME }}
|
||||
github-app-client-id: ${{ secrets.GH_APP_CLIENT_ID }}
|
||||
github-app-installation-id: ${{ secrets.GH_APP_INSTALLATION_ID }}
|
||||
repository: ${{ github.repository }}
|
||||
permission-profile: pull-requests
|
||||
fallback-token: ${{ secrets.GH_ACTIONS_PR_WRITE }}
|
||||
|
||||
- uses: actions/labeler@b8dd2d9be0f68b860e7dae5dae7d772984eacd6d # v6.2.0
|
||||
with:
|
||||
repo-token: ${{ steps.github-auth.outputs.token }}
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- uses: actions/github-script@v6
|
||||
- uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
name: "Issue/PR: update title"
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -13,13 +13,13 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
# check out the latest version of the code
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
# Checks the status of hyperlinks in all files
|
||||
- name: Run linkspector
|
||||
uses: umbrelladocs/action-linkspector@v1
|
||||
uses: umbrelladocs/action-linkspector@568ec8d29fa92b31fd9ea5381e155c51e922af83 # v1.5.5
|
||||
with:
|
||||
reporter: local
|
||||
filter_mode: nofilter
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
# NOTE: v1 is updated to reflect the latest v1.x.y. Please use any tag/branch that suits your needs:
|
||||
# https://github.com/upsidr/merge-gatekeeper/tags
|
||||
# https://github.com/upsidr/merge-gatekeeper/branches
|
||||
uses: upsidr/merge-gatekeeper@v1
|
||||
uses: upsidr/merge-gatekeeper@09af7a82c1666d0e64d2bd8c01797a0bcfd3bb5d # v1.2.1
|
||||
if: github.event_name == 'pull_request'
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -17,9 +17,9 @@ jobs:
|
||||
env:
|
||||
UV_PYTHON: "3.10"
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
|
||||
with:
|
||||
version: "0.5.x"
|
||||
enable-cache: true
|
||||
@@ -31,18 +31,18 @@ jobs:
|
||||
- name: Build the package
|
||||
run: cd python && make build
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
|
||||
with:
|
||||
files: |
|
||||
python/dist/*
|
||||
- name: Azure Login
|
||||
uses: azure/login@v2
|
||||
uses: azure/login@7184910d9eb2b1c5e48f7073824a90609bb9b6d6 # v2.3.1
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
||||
- name: Start DevOps pipeline
|
||||
uses: azure/cli@v2
|
||||
uses: azure/cli@9eb25b8360668fb0ecbafa808d40e2197b2f5f52 # v3.0.0
|
||||
with:
|
||||
inlineScript: |
|
||||
az pipelines run --id ${{ vars.ADO_PYTHON_RELEASE_ID }} --org ${{ vars.ADO_ORG }} --project ${{ vars.ADO_PROJECT_NAME }} --parameters tag=${{ github.event.release.tag_name }} delay=0
|
||||
|
||||
@@ -84,8 +84,8 @@ jobs:
|
||||
outputs:
|
||||
pythonChanges: ${{ steps.filter.outputs.python}}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: dorny/paths-filter@v2
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
|
||||
id: filter
|
||||
with:
|
||||
filters: |
|
||||
@@ -119,9 +119,9 @@ jobs:
|
||||
UV_PYTHON: ${{ matrix.python-version }}
|
||||
COMPLETIONS_CONCEPT_SAMPLE: "true"
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
|
||||
with:
|
||||
version: "0.5.x"
|
||||
enable-cache: true
|
||||
@@ -131,21 +131,23 @@ jobs:
|
||||
run: |
|
||||
uv sync --all-extras --dev
|
||||
- name: Google auth
|
||||
uses: google-github-actions/auth@v3
|
||||
uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0
|
||||
with:
|
||||
project_id: ${{ vars.VERTEX_AI_PROJECT_ID }}
|
||||
credentials_json: ${{ secrets.VERTEX_AI_SERVICE_ACCOUNT_KEY }}
|
||||
- name: Set up gcloud
|
||||
uses: google-github-actions/setup-gcloud@v3
|
||||
uses: google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db # v3.0.1
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
# Bedrock tests are disabled while the integration credentials are invalid.
|
||||
if: false
|
||||
uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
- name: Azure CLI Login
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: azure/login@v2
|
||||
uses: azure/login@7184910d9eb2b1c5e48f7073824a90609bb9b6d6 # v2.3.1
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
@@ -154,7 +156,7 @@ jobs:
|
||||
id: run_tests_ai_services
|
||||
shell: bash
|
||||
run: |
|
||||
uv run pytest -v --log-cli-level=INFO --durations=20 -n logical --dist loadfile --dist worksteal -m "not ollama" ./tests/integration/completions ./tests/integration/embeddings ./tests/samples ./tests/integration/cross_language
|
||||
uv run pytest -v --log-cli-level=INFO --durations=20 -n logical --dist loadfile --dist worksteal -m "not ollama" -k "not bedrock" ./tests/integration/completions ./tests/integration/embeddings ./tests/samples ./tests/integration/cross_language
|
||||
|
||||
python-merge-gate-multi-modality:
|
||||
name: Python Pre-Merge Integration Tests - Multi-Modality
|
||||
@@ -174,9 +176,9 @@ jobs:
|
||||
env:
|
||||
UV_PYTHON: ${{ matrix.python-version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
|
||||
with:
|
||||
version: "0.5.x"
|
||||
enable-cache: true
|
||||
@@ -186,7 +188,7 @@ jobs:
|
||||
uv sync --all-extras --dev
|
||||
- name: Azure CLI Login
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: azure/login@v2
|
||||
uses: azure/login@7184910d9eb2b1c5e48f7073824a90609bb9b6d6 # v2.3.1
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
@@ -215,9 +217,9 @@ jobs:
|
||||
env:
|
||||
UV_PYTHON: ${{ matrix.python-version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
|
||||
with:
|
||||
version: "0.5.x"
|
||||
enable-cache: true
|
||||
@@ -226,14 +228,16 @@ jobs:
|
||||
run: |
|
||||
uv sync --all-extras --dev
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
# Bedrock tests are disabled while the integration credentials are invalid.
|
||||
if: false
|
||||
uses: aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708 # v5.1.1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
- name: Azure CLI Login
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: azure/login@v2
|
||||
uses: azure/login@7184910d9eb2b1c5e48f7073824a90609bb9b6d6 # v2.3.1
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
@@ -242,7 +246,7 @@ jobs:
|
||||
id: run_tests_agents
|
||||
shell: bash
|
||||
run: |
|
||||
uv run pytest -v --log-cli-level=INFO --durations=20 -n logical --dist loadfile --dist worksteal ./tests/integration/agents
|
||||
uv run pytest -v --log-cli-level=INFO --durations=20 -n logical --dist loadfile --dist worksteal -k "not bedrock" ./tests/integration/agents
|
||||
|
||||
python-merge-gate-ollama:
|
||||
name: Python Pre-Merge Integration Tests - Ollama
|
||||
@@ -264,9 +268,9 @@ jobs:
|
||||
UV_PYTHON: ${{ matrix.python-version }}
|
||||
COMPLETIONS_CONCEPT_SAMPLE: "true"
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
|
||||
with:
|
||||
version: "0.5.x"
|
||||
enable-cache: true
|
||||
@@ -329,9 +333,9 @@ jobs:
|
||||
- 8080:8080
|
||||
- 50051:50051
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
|
||||
with:
|
||||
version: "0.5.x"
|
||||
enable-cache: true
|
||||
@@ -342,7 +346,7 @@ jobs:
|
||||
uv sync --all-extras --dev
|
||||
- name: Azure CLI Login
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: azure/login@v2
|
||||
uses: azure/login@7184910d9eb2b1c5e48f7073824a90609bb9b6d6 # v2.3.1
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
@@ -387,9 +391,9 @@ jobs:
|
||||
- 8080:8080
|
||||
- 50051:50051
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
|
||||
with:
|
||||
version: "0.5.x"
|
||||
enable-cache: true
|
||||
@@ -415,14 +419,16 @@ jobs:
|
||||
ollama pull ${{ vars.OLLAMA_EMBEDDING_MODEL_ID }}
|
||||
ollama list
|
||||
- name: Google auth
|
||||
uses: google-github-actions/auth@v3
|
||||
uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0
|
||||
with:
|
||||
project_id: ${{ vars.VERTEX_AI_PROJECT_ID }}
|
||||
credentials_json: ${{ secrets.VERTEX_AI_SERVICE_ACCOUNT_KEY }}
|
||||
- name: Set up gcloud
|
||||
uses: google-github-actions/setup-gcloud@v3
|
||||
uses: google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db # v3.0.1
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
# Bedrock tests are disabled while the integration credentials are invalid.
|
||||
if: false
|
||||
uses: aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708 # v5.1.1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
@@ -435,7 +441,7 @@ jobs:
|
||||
Start-CosmosDbEmulator
|
||||
- name: Azure CLI Login
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: azure/login@v2
|
||||
uses: azure/login@7184910d9eb2b1c5e48f7073824a90609bb9b6d6 # v2.3.1
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
@@ -446,14 +452,14 @@ jobs:
|
||||
shell: bash
|
||||
# Ollama tests are very unstable at the moment. It often fails to pull models from the Ollama server. Thus, Ollama is disabled for now.
|
||||
run: |
|
||||
uv run pytest -v -n logical --dist loadfile --dist worksteal -m "not ollama" ./tests/integration/completions
|
||||
uv run pytest -v -n logical --dist loadfile --dist worksteal -m "not ollama" -k "not bedrock" ./tests/integration/completions
|
||||
- name: Run Integration Tests - Embeddings
|
||||
id: run_tests_embeddings
|
||||
timeout-minutes: 5
|
||||
shell: bash
|
||||
# Ollama tests are very unstable at the moment. It often fails to pull models from the Ollama server. Thus, Ollama is disabled for now.
|
||||
run: |
|
||||
uv run pytest -v -n logical --dist loadfile --dist worksteal -m "not ollama" ./tests/integration/embeddings
|
||||
uv run pytest -v -n logical --dist loadfile --dist worksteal -m "not ollama" -k "not bedrock" ./tests/integration/embeddings
|
||||
- name: Run Integration Tests - Memory
|
||||
id: run_tests_memory
|
||||
timeout-minutes: 5
|
||||
@@ -483,7 +489,7 @@ jobs:
|
||||
timeout-minutes: 10
|
||||
shell: bash
|
||||
run: |
|
||||
uv run pytest -v -n logical --dist loadfile --dist worksteal ./tests/integration/agents
|
||||
uv run pytest -v -n logical --dist loadfile --dist worksteal -k "not bedrock" ./tests/integration/agents
|
||||
- name: Run Integration Tests - Multi-Modality
|
||||
id: run_tests_multi_modality
|
||||
timeout-minutes: 5
|
||||
@@ -534,19 +540,19 @@ jobs:
|
||||
- name: Fail workflow if tests failed
|
||||
id: check_tests_failed
|
||||
if: contains(join(needs.*.result, ','), 'failure')
|
||||
uses: actions/github-script@v6
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
with:
|
||||
script: core.setFailed('Integration Tests Failed!')
|
||||
|
||||
- name: Fail workflow if tests cancelled
|
||||
id: check_tests_cancelled
|
||||
if: contains(join(needs.*.result, ','), 'cancelled')
|
||||
uses: actions/github-script@v6
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
with:
|
||||
script: core.setFailed('Integration Tests Cancelled!')
|
||||
|
||||
- name: Microsoft Teams Notification
|
||||
uses: skitionek/notify-microsoft-teams@v1.0.9
|
||||
uses: skitionek/notify-microsoft-teams@216b8b28967e7e89b0b64b81dc94aeae90e642ab # v1.3.0
|
||||
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
|
||||
with:
|
||||
webhook_url: ${{ secrets.MSTEAMS_WEBHOOK }}
|
||||
@@ -556,7 +562,7 @@ jobs:
|
||||
title: "{title: ` ${{ env.run_type }}: ${{ env.date }} `, text: ` ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}`}"
|
||||
|
||||
- name: Microsoft Teams Notification (Dry Run)
|
||||
uses: skitionek/notify-microsoft-teams@v1.0.9
|
||||
uses: skitionek/notify-microsoft-teams@216b8b28967e7e89b0b64b81dc94aeae90e642ab # v1.3.0
|
||||
if: github.ref != 'refs/heads/main'
|
||||
with:
|
||||
webhook_url: NONE
|
||||
|
||||
@@ -23,9 +23,9 @@ jobs:
|
||||
UV_CACHE_DIR: /tmp/.uv-cache
|
||||
UV_PYTHON: ${{ matrix.python-version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
|
||||
with:
|
||||
version: "0.5.x"
|
||||
enable-cache: true
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
cache-dependency-glob: "**/uv.lock"
|
||||
- name: Install the project
|
||||
run: uv sync --all-extras --dev
|
||||
- uses: pre-commit/[email protected]
|
||||
- uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
|
||||
name: Run Pre-Commit Hooks
|
||||
with:
|
||||
extra_args: --config python/.pre-commit-config.yaml --all-files
|
||||
|
||||
@@ -18,13 +18,13 @@ jobs:
|
||||
environment: "integration"
|
||||
steps:
|
||||
- name: Azure Login
|
||||
uses: azure/login@v2
|
||||
uses: azure/login@7184910d9eb2b1c5e48f7073824a90609bb9b6d6 # v2.3.1
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
||||
- name: Start DevOps pipeline
|
||||
uses: azure/cli@v2
|
||||
uses: azure/cli@9eb25b8360668fb0ecbafa808d40e2197b2f5f52 # v3.0.0
|
||||
with:
|
||||
inlineScript: |
|
||||
az pipelines run --id ${{ vars.ADO_PYTHON_RELEASE_ID }} --org ${{ vars.ADO_ORG }} --project ${{ vars.ADO_PROJECT_NAME }} --parameters tag=${{ inputs.tag }} delay=0
|
||||
|
||||
@@ -8,6 +8,7 @@ on:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
@@ -19,11 +20,11 @@ jobs:
|
||||
run:
|
||||
working-directory: python
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Download coverage report
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
|
||||
with:
|
||||
github-token: ${{ secrets.GH_ACTIONS_PR_WRITE }}
|
||||
github-token: ${{ github.token }}
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
path: ./python
|
||||
merge-multiple: true
|
||||
@@ -35,13 +36,17 @@ jobs:
|
||||
# The PR number is needed to post the comment on the PR
|
||||
run: |
|
||||
PR_NUMBER=$(cat pr_number)
|
||||
if ! [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then
|
||||
echo "::error::PR number file contains invalid content"
|
||||
exit 1
|
||||
fi
|
||||
echo "PR number: $PR_NUMBER"
|
||||
echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV
|
||||
- name: Pytest coverage comment
|
||||
id: coverageComment
|
||||
uses: MishaKav/[email protected]
|
||||
uses: MishaKav/pytest-coverage-comment@1bdbba85fb74a2fdc1ec66383acec1091610f82b # v1.1.57
|
||||
with:
|
||||
github-token: ${{ secrets.GH_ACTIONS_PR_WRITE }}
|
||||
github-token: ${{ github.token }}
|
||||
issue-number: ${{ env.PR_NUMBER }}
|
||||
pytest-xml-coverage-path: python/python-coverage.xml
|
||||
title: "Python Test Coverage Report"
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
env:
|
||||
UV_PYTHON: "3.10"
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
# Save the PR number to a file since the workflow_run event
|
||||
# in the coverage report workflow does not have access to it
|
||||
- name: Save PR number
|
||||
run: |
|
||||
echo ${{ github.event.number }} > ./pr_number
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
|
||||
with:
|
||||
version: "0.5.x"
|
||||
enable-cache: true
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
- name: Test with pytest
|
||||
run: uv run --frozen pytest -q --junitxml=pytest.xml --cov=semantic_kernel --cov-report=term-missing:skip-covered --cov-report=xml:python-coverage.xml ./tests/unit --ignore=./tests/unit/processes/dapr_runtime
|
||||
- name: Upload coverage report
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
path: |
|
||||
python/python-coverage.xml
|
||||
|
||||
@@ -39,9 +39,9 @@ jobs:
|
||||
run:
|
||||
working-directory: python
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
|
||||
with:
|
||||
version: "0.5.x"
|
||||
enable-cache: true
|
||||
@@ -65,7 +65,7 @@ jobs:
|
||||
run: uv run --frozen pytest --junitxml=pytest-dapr.xml ./tests/unit/processes/dapr_runtime
|
||||
- name: Surface failing tests
|
||||
if: ${{ !matrix.experimental && matrix.test-suite == 'unit-all-except-dapr' }}
|
||||
uses: pmeier/pytest-results-action@v0.7.2
|
||||
uses: pmeier/pytest-results-action@fdc7f18d9934e38aca411ca9557e6577bd25ca9c # v0.9.0
|
||||
with:
|
||||
path: python/pytest.xml
|
||||
summary: true
|
||||
|
||||
@@ -20,12 +20,20 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: jitterbit/get-changed-files@b17fbb00bdc0c0f63fcf166580804b4d2cdc2a42 # v1
|
||||
continue-on-error: true
|
||||
|
||||
- name: Use custom config file
|
||||
uses: crate-ci/typos@v1.36.2
|
||||
uses: crate-ci/typos@631208b7aac2daa8b707f55e7331f9112b0e062d # v1.44.0
|
||||
with:
|
||||
files: ${{ github.event_name == 'pull_request' && steps.changed-files.outputs.added_modified || '.' }}
|
||||
config: .github/_typos.toml
|
||||
write_changes: false
|
||||
|
||||
@@ -502,3 +502,5 @@ swa-cli.config.json
|
||||
|
||||
# dapr extension files
|
||||
**/dapr.yaml
|
||||
|
||||
*.lscache
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# Semantic Kernel
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Semantic Kernel is now [Microsoft Agent Framework](https://github.com/microsoft/agent-framework)! Microsoft Agent Framework (MAF) is the enterprise‑ready successor to Semantic Kernel. Microsoft Agent Framework is now available at version 1.0 as a production-ready release: stable APIs, and a commitment to long-term support. Whether you're building a single assistant or orchestrating a fleet of specialized agents, Microsoft Agent Framework 1.0 gives you enterprise-grade multi-agent orchestration, multi-provider model support, and cross-runtime interoperability via A2A and MCP.
|
||||
>
|
||||
> Learn more about Semantic Kernel and Agent Framework here: [Semantic Kernel and Microsoft Agent Framework on the Agent Framework blog](https://devblogs.microsoft.com/agent-framework/semantic-kernel-and-microsoft-agent-framework/), and try out the [Semantic Kernel migration guide](https://learn.microsoft.com/en-us/agent-framework/migration-guide/from-semantic-kernel).
|
||||
|
||||
**Build intelligent AI agents and multi-agent systems with this enterprise-ready orchestration framework**
|
||||
|
||||
[](https://github.com/microsoft/semantic-kernel/blob/main/LICENSE)
|
||||
@@ -7,7 +12,6 @@
|
||||
[](https://www.nuget.org/packages/Microsoft.SemanticKernel/)
|
||||
[](https://aka.ms/SKDiscord)
|
||||
|
||||
|
||||
## What is Semantic Kernel?
|
||||
|
||||
Semantic Kernel is a model-agnostic SDK that empowers developers to build, orchestrate, and deploy AI agents and multi-agent systems. Whether you're building a simple chatbot or a complex multi-agent workflow, Semantic Kernel provides the tools you need with enterprise-grade reliability and flexibility.
|
||||
|
||||
@@ -144,7 +144,7 @@ Currently the priorities are ordered but not necessarily needs to be implemented
|
||||
|
||||
Chosen option: "Feature Branch Strategy", because it allows individual features to be developed in isolation, minimizing conflicts with the main branch and facilitating easier code reviews.
|
||||
|
||||
## Fequent Asked Questions
|
||||
## Frequent Asked Questions
|
||||
|
||||
### Is there a migration strategy for initiatives that followed the old contribution way with forks, and now have to switch to branches in microsoft/semantic-kernel?
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ public sealed record FunctionView(
|
||||
| Type | Pros | Cons |
|
||||
| ------------------------- | ------------------------------------------------------------ | ---------------------------------------------------------- |
|
||||
| JsonSchema.Net.JsonSchema | Popular and has frequent updates, built on top of System.Net | Takes a dependency on OSS in SK core |
|
||||
| NJsonShema.JsonSchema | Very popular, frequent updates, long term project | Built on top of Json.Net (Newtonsoft) |
|
||||
| NJsonSchema.JsonSchema | Very popular, frequent updates, long term project | Built on top of Json.Net (Newtonsoft) |
|
||||
| JsonDocument | Native C# type, fast and flexible | Not a Json Schema, but a Json DOM container for the schema |
|
||||
| String | Native C# type | Not a Json Schema or Json DOM, very poor type hinting |
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
# Reestructure of How Sample Code will be Structured In the Repository
|
||||
# Restructure of How Sample Code will be Structured In the Repository
|
||||
|
||||
status: accepted
|
||||
contact: rogerbarreto
|
||||
@@ -228,7 +228,7 @@ Identified Component Oriented Concepts:
|
||||
|
||||
- Planners
|
||||
|
||||
- Handlerbars
|
||||
- Handlebars
|
||||
|
||||
- Authentication
|
||||
|
||||
@@ -358,7 +358,7 @@ Concepts/
|
||||
│ ├── Resiliency/
|
||||
│ └── Usage/
|
||||
├── Planners/
|
||||
│ └── Handlerbars/
|
||||
│ └── Handlebars/
|
||||
├── Authentication/
|
||||
│ └── Azure AD/
|
||||
├── Function Calling/
|
||||
@@ -420,7 +420,7 @@ Concepts/
|
||||
│ ├── Resiliency/
|
||||
│ └── Usage/
|
||||
├── Planners/
|
||||
│ └── Handlerbars/
|
||||
│ └── Handlebars/
|
||||
├── Authentication/
|
||||
│ └── Azure AD/
|
||||
├── Function Calling/
|
||||
@@ -502,7 +502,7 @@ Concepts/
|
||||
├── DependencyInjection
|
||||
├── HttpClient.Resiliency
|
||||
├── HttpClient.Usage
|
||||
├── Planners.Handlerbars
|
||||
├── Planners.Handlebars
|
||||
├── Authentication.AzureAD
|
||||
├── FunctionCalling.AutoFunctionCalling
|
||||
├── FunctionCalling.ManualFunctionCalling
|
||||
@@ -545,7 +545,7 @@ Concepts/
|
||||
├── Logging
|
||||
├── DependencyInjection
|
||||
├── HttpClient
|
||||
├── Planners.Handlerbars
|
||||
├── Planners.Handlebars
|
||||
├── Authentication.AzureAD
|
||||
├── FunctionCalling
|
||||
├── Filtering
|
||||
@@ -634,7 +634,7 @@ Concepts/
|
||||
|
||||
Pros:
|
||||
|
||||
- Beginers will be oriented to the right difficulty level and examples will be more organized by complexity
|
||||
- Beginners will be oriented to the right difficulty level and examples will be more organized by complexity
|
||||
|
||||
Cons:
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ await ragStore.UpsertDocumentsAsync(
|
||||
var agentThread = new ChatHistoryAgentThread();
|
||||
agentThread.ThreadExtensionsManager.RegisterThreadExtension(ragComponent);
|
||||
|
||||
// Inovke the agent.
|
||||
// Invoke the agent.
|
||||
var asyncResults1 = agent.InvokeAsync("What was the income of Contoso for 2023", agentThread);
|
||||
// Expected response contains the 174M income from the document.
|
||||
```
|
||||
|
||||
@@ -6,27 +6,27 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Aspire.Azure.AI.OpenAI" Version="9.3.1-preview.1.25305.6" />
|
||||
<PackageVersion Include="Aspire.Azure.Search.Documents" Version="9.5.1" />
|
||||
<PackageVersion Include="Aspire.Hosting.AppHost" Version="13.0.0" />
|
||||
<PackageVersion Include="Aspire.Hosting.Azure.CognitiveServices" Version="13.0.0" />
|
||||
<PackageVersion Include="Aspire.Azure.Search.Documents" Version="13.4.6" />
|
||||
<PackageVersion Include="Aspire.Hosting.AppHost" Version="13.4.6" />
|
||||
<PackageVersion Include="Aspire.Hosting.Azure.CognitiveServices" Version="13.4.6" />
|
||||
<PackageVersion Include="Aspire.Hosting.NodeJs" Version="9.5.2" />
|
||||
<PackageVersion Include="CommunityToolkit.Aspire.Hosting.Dapr" Version="9.9.0" />
|
||||
<PackageVersion Include="CommunityToolkit.Aspire.Hosting.NodeJS.Extensions" Version="9.9.0" />
|
||||
<PackageVersion Include="Aspire.Hosting.Azure.Search" Version="13.0.0" />
|
||||
<PackageVersion Include="AWSSDK.BedrockAgent" Version="4.0.7.5" />
|
||||
<PackageVersion Include="AWSSDK.BedrockAgentRuntime" Version="4.0.8.5" />
|
||||
<PackageVersion Include="AWSSDK.BedrockRuntime" Version="4.0.14.5" />
|
||||
<PackageVersion Include="AWSSDK.Core" Version="4.0.3.8" />
|
||||
<PackageVersion Include="AWSSDK.Extensions.Bedrock.MEAI" Version="4.0.5.3" />
|
||||
<PackageVersion Include="AWSSDK.Extensions.NETCore.Setup" Version="4.0.3.19" />
|
||||
<PackageVersion Include="AWSSDK.SecurityToken" Version="4.0.5.6" />
|
||||
<PackageVersion Include="Aspire.Hosting.Azure.Search" Version="13.4.6" />
|
||||
<PackageVersion Include="MessagePack" Version="3.1.7" /> <!-- Transitive dependency of Aspire pinned to newer version due to vulnerability in 2.5.192 -->
|
||||
<PackageVersion Include="AWSSDK.BedrockAgent" Version="4.0.100.8" />
|
||||
<PackageVersion Include="AWSSDK.BedrockAgentRuntime" Version="4.0.100.7" />
|
||||
<PackageVersion Include="AWSSDK.BedrockRuntime" Version="4.0.101.1" />
|
||||
<PackageVersion Include="AWSSDK.Core" Version="4.0.101" />
|
||||
<PackageVersion Include="AWS.Bedrock.MEAI" Version="1.0.0" />
|
||||
<PackageVersion Include="AWSSDK.Extensions.NETCore.Setup" Version="4.0.100.7" />
|
||||
<PackageVersion Include="AWSSDK.SecurityToken" Version="4.0.100.7" />
|
||||
<PackageVersion Include="Azure.AI.Agents.Persistent" Version="1.1.0" />
|
||||
<PackageVersion Include="Azure.AI.ContentSafety" Version="1.0.0" />
|
||||
<PackageVersion Include="Azure.AI.OpenAI" Version="2.9.0-beta.1" />
|
||||
<PackageVersion Include="Azure.AI.Projects" Version="2.0.0-beta.2" />
|
||||
<PackageVersion Include="Azure.Identity" Version="1.19.0" />
|
||||
<PackageVersion Include="Azure.Monitor.OpenTelemetry.Exporter" Version="1.5.0" />
|
||||
<PackageVersion Include="Azure.Search.Documents" Version="11.7.0" />
|
||||
<PackageVersion Include="Azure.AI.Projects" Version="2.0.1" />
|
||||
<PackageVersion Include="Azure.Identity" Version="1.21.0" />
|
||||
<PackageVersion Include="Azure.Monitor.OpenTelemetry.Exporter" Version="1.8.3" />
|
||||
<PackageVersion Include="Community.OData.Linq" Version="2.1.0" />
|
||||
<PackageVersion Include="Dapr.Actors" Version="1.16.1" />
|
||||
<PackageVersion Include="Dapr.Actors.AspNetCore" Version="1.16.1" />
|
||||
@@ -50,22 +50,24 @@
|
||||
<PackageVersion Include="JsonSchema.Net" Version="7.3.4" />
|
||||
<PackageVersion Include="JsonSchema.Net.Generation" Version="5.0.2" />
|
||||
<PackageVersion Include="Markdig" Version="0.40.0" />
|
||||
<PackageVersion Include="Microsoft.Agents.AI.Abstractions" Version="1.0.0-preview.251009.1" />
|
||||
<PackageVersion Include="Microsoft.Agents.AI.OpenAI" Version="1.0.0-preview.251009.1" />
|
||||
<PackageVersion Include="Microsoft.Agents.AI.AzureAI" Version="1.0.0-preview.251009.1" />
|
||||
<PackageVersion Include="Microsoft.Agents.AI.Workflows" Version="1.0.0-preview.251009.1" />
|
||||
<PackageVersion Include="Microsoft.Agents.AI.Abstractions" Version="1.0.0" />
|
||||
<PackageVersion Include="Microsoft.Agents.AI.Foundry" Version="1.0.0" />
|
||||
<PackageVersion Include="Microsoft.Agents.AI.OpenAI" Version="1.0.0" />
|
||||
<PackageVersion Include="Microsoft.Agents.AI.Workflows" Version="1.0.0" />
|
||||
<PackageVersion Include="Microsoft.Agents.CopilotStudio.Client" Version="1.1.107-beta" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.13" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="8.0.14" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.OData" Version="9.5.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="8.0.30" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Client" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Azure.Functions.Worker" Version="2.0.0" />
|
||||
<PackageVersion Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.3.0" />
|
||||
<PackageVersion Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="2.0.0" />
|
||||
<PackageVersion Include="Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues" Version="5.5.0" />
|
||||
<PackageVersion Include="Microsoft.Azure.Functions.Worker.SDK" Version="2.0.0" />
|
||||
<PackageVersion Include="Microsoft.Azure.Kusto.Data" Version="12.2.8" />
|
||||
<PackageVersion Include="Microsoft.Azure.WebJobs.Extensions.OpenApi" Version="1.5.1" />
|
||||
<PackageVersion Include="Microsoft.Azure.WebJobs.Extensions.OpenApi" Version="1.6.0" />
|
||||
<PackageVersion Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="5.3.2" />
|
||||
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.4" />
|
||||
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.6" />
|
||||
<PackageVersion Include="Microsoft.Bcl.HashCode" Version="1.1.1" />
|
||||
<PackageVersion Include="Microsoft.Bcl.Memory" Version="10.0.4" />
|
||||
<PackageVersion Include="Microsoft.Bcl.Numerics" Version="10.0.2" />
|
||||
@@ -73,10 +75,11 @@
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.13.0" />
|
||||
<PackageVersion Include="Microsoft.Identity.Client" Version="4.81.0" />
|
||||
<PackageVersion Include="Microsoft.Identity.Client.Extensions.Msal" Version="4.81.0" />
|
||||
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.15.0" />
|
||||
<PackageVersion Include="Microsoft.Kiota.Authentication.Azure" Version="1.21.1" />
|
||||
<PackageVersion Include="Microsoft.Kiota.Http.HttpClientLibrary" Version="1.21.1" />
|
||||
<PackageVersion Include="Microsoft.Kiota.Serialization.Json" Version="1.21.1" />
|
||||
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.16.0" />
|
||||
<PackageVersion Include="Microsoft.Kiota.Abstractions" Version="1.22.2" />
|
||||
<PackageVersion Include="Microsoft.Kiota.Authentication.Azure" Version="1.22.2" />
|
||||
<PackageVersion Include="Microsoft.Kiota.Http.HttpClientLibrary" Version="1.22.2" />
|
||||
<PackageVersion Include="Microsoft.Kiota.Serialization.Json" Version="1.22.2" />
|
||||
<PackageVersion Include="Microsoft.ML.OnnxRuntime" Version="1.23.2" />
|
||||
<PackageVersion Include="Microsoft.ML.OnnxRuntime.Gpu" Version="1.23.2" />
|
||||
<PackageVersion Include="Microsoft.ML.Tokenizers.Data.Cl100kBase" Version="2.0.0" />
|
||||
@@ -85,34 +88,34 @@
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Core" Version="1.71.0" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Planners.OpenAI" Version="1.47.0-preview" />
|
||||
<PackageVersion Include="Microsoft.VisualStudio.Threading" Version="17.14.15" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Client" Version="10.0.2" />
|
||||
<PackageVersion Include="ModelContextProtocol" Version="0.4.0-preview.3" />
|
||||
<PackageVersion Include="MSTest.TestFramework" Version="3.8.0" />
|
||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageVersion Include="Npgsql" Version="10.0.2" />
|
||||
<PackageVersion Include="Npgsql" Version="10.0.3" />
|
||||
<PackageVersion Include="OData2Linq" Version="2.2.0" />
|
||||
<PackageVersion Include="OllamaSharp" Version="5.4.12" />
|
||||
<PackageVersion Include="OpenAI" Version="2.9.1" />
|
||||
<PackageVersion Include="OpenTelemetry.Exporter.Console" Version="1.14.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.14.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.14.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.14.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="1.14.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.Runtime" Version="1.14.0" />
|
||||
<PackageVersion Include="OllamaSharp" Version="5.4.25" />
|
||||
<PackageVersion Include="OpenAI" Version="2.10.0" />
|
||||
<PackageVersion Include="OpenTelemetry" Version="1.15.3" />
|
||||
<PackageVersion Include="OpenTelemetry.Api" Version="1.15.3" />
|
||||
<PackageVersion Include="OpenTelemetry.Api.ProviderBuilderExtensions" Version="1.15.3" />
|
||||
<PackageVersion Include="OpenTelemetry.Exporter.Console" Version="1.15.3" />
|
||||
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.15.3" />
|
||||
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.15.3" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.15.2" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="1.15.1" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.Runtime" Version="1.15.1" />
|
||||
<PackageVersion Include="PdfPig" Version="0.1.13" />
|
||||
<PackageVersion Include="Pinecone.Client" Version="3.1.0" />
|
||||
<PackageVersion Include="Prompty.Core" Version="0.2.3-beta" />
|
||||
<PackageVersion Include="Scriban" Version="7.0.3" />
|
||||
<PackageVersion Include="Prompty.Core" Version="2.0.0-beta.3" />
|
||||
<PackageVersion Include="PuppeteerSharp" Version="20.2.5" />
|
||||
<PackageVersion Include="System.Diagnostics.DiagnosticSource" Version="10.0.2" />
|
||||
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.15.0" />
|
||||
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.16.0" />
|
||||
<PackageVersion Include="System.IO.Packaging" Version="10.0.2" />
|
||||
<PackageVersion Include="System.Linq.AsyncEnumerable" Version="10.0.4" />
|
||||
<PackageVersion Include="System.Memory.Data" Version="10.0.2" />
|
||||
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
|
||||
<PackageVersion Include="System.Numerics.Tensors" Version="10.0.4" />
|
||||
<PackageVersion Include="System.Text.Json" Version="10.0.4" />
|
||||
<PackageVersion Include="System.ValueTuple" Version="4.6.1" />
|
||||
<PackageVersion Include="System.Numerics.Tensors" Version="10.0.10" />
|
||||
<PackageVersion Include="System.Text.Json" Version="10.0.6" />
|
||||
<PackageVersion Include="System.ValueTuple" Version="4.6.2" />
|
||||
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.6.3" />
|
||||
<PackageVersion Include="A2A" Version="0.3.1-preview" />
|
||||
<PackageVersion Include="A2A.AspNetCore" Version="0.3.1-preview" />
|
||||
@@ -120,10 +123,10 @@
|
||||
<!-- Tokenizers -->
|
||||
<PackageVersion Include="Microsoft.ML.Tokenizers" Version="2.0.0" />
|
||||
<!-- Microsoft.Extensions.* -->
|
||||
<PackageVersion Include="Microsoft.Extensions.AI" Version="10.4.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.AI.Abstractions" Version="10.4.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.AI" Version="10.5.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.AI.Abstractions" Version="10.5.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.AI.AzureAIInference" Version="10.0.0-preview.1.25559.3" />
|
||||
<PackageVersion Include="Microsoft.Extensions.AI.OpenAI" Version="10.4.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.AI.OpenAI" Version="10.5.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.2" />
|
||||
@@ -132,27 +135,29 @@
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.UserSecrets" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.4" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.6" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Diagnostics.Testing" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Http" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="10.2.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.ServiceDiscovery" Version="10.2.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.4" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.9" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Debug" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Options.DataAnnotations" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Bcl.TimeProvider" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.TimeProvider.Testing" Version="10.2.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.FileProviders.Physical" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.VectorData.Abstractions" Version="10.5.2" />
|
||||
<!-- Test -->
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
|
||||
<PackageVersion Include="Moq" Version="[4.18.4]" />
|
||||
<PackageVersion Include="FluentAssertions" Version="8.2.0" />
|
||||
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
|
||||
<PackageVersion Include="System.Threading.Channels" Version="10.0.4" />
|
||||
<PackageVersion Include="System.Threading.Channels" Version="10.0.6" />
|
||||
<PackageVersion Include="System.Threading.Tasks.Dataflow" Version="10.0.2" />
|
||||
<PackageVersion Include="xunit" Version="2.9.3" />
|
||||
<PackageVersion Include="xunit.abstractions" Version="2.0.3" />
|
||||
@@ -164,13 +169,12 @@
|
||||
<PackageVersion Include="Humanizer" Version="2.14.1" />
|
||||
<!-- Plugins -->
|
||||
<PackageVersion Include="DocumentFormat.OpenXml" Version="3.3.0" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.10" />
|
||||
<PackageVersion Include="DuckDB.NET.Data.Full" Version="1.2.0" />
|
||||
<PackageVersion Include="DuckDB.NET.Data" Version="1.1.3" />
|
||||
<PackageVersion Include="MongoDB.Driver" Version="3.5.2" />
|
||||
<PackageVersion Include="Microsoft.Graph" Version="5.94.0" />
|
||||
<PackageVersion Include="Microsoft.OpenApi" Version="1.6.24" />
|
||||
<PackageVersion Include="Microsoft.OpenApi.Readers" Version="1.6.24" />
|
||||
<PackageVersion Include="Microsoft.Graph" Version="5.105.0" />
|
||||
<PackageVersion Include="Microsoft.Graph.Core" Version="3.2.6" />
|
||||
<PackageVersion Include="Microsoft.OpenApi" Version="1.6.31" />
|
||||
<PackageVersion Include="Microsoft.OpenApi.Readers" Version="1.6.31" />
|
||||
<PackageVersion Include="Microsoft.OpenApi.ApiManifest" Version="0.5.6-preview" />
|
||||
<PackageVersion Include="Microsoft.Plugins.Manifest" Version="1.0.0-rc3" />
|
||||
<PackageVersion Include="protobuf-net" Version="3.2.56" />
|
||||
@@ -178,20 +182,18 @@
|
||||
<PackageVersion Include="YamlDotNet" Version="16.3.0" />
|
||||
<PackageVersion Include="Fluid.Core" Version="2.31.0" />
|
||||
<!-- Memory stores -->
|
||||
<PackageVersion Include="Microsoft.Azure.Cosmos" Version="3.54.0" />
|
||||
<PackageVersion Include="Pgvector" Version="0.3.2" />
|
||||
<PackageVersion Include="sqlite-vec" Version="0.1.7-alpha.2.1" />
|
||||
<PackageVersion Include="NRedisStack" Version="1.0.0" />
|
||||
<PackageVersion Include="Milvus.Client" Version="2.3.0-preview.1" />
|
||||
<PackageVersion Include="Testcontainers" Version="4.10.0" />
|
||||
<PackageVersion Include="Testcontainers.Milvus" Version="4.8.1" />
|
||||
<PackageVersion Include="Testcontainers.MongoDB" Version="4.6.0" />
|
||||
<PackageVersion Include="Testcontainers.MsSql" Version="4.6.0" />
|
||||
<PackageVersion Include="Testcontainers.PostgreSql" Version="4.6.0" />
|
||||
<PackageVersion Include="Testcontainers.Qdrant" Version="4.10.0" />
|
||||
<PackageVersion Include="Testcontainers.Redis" Version="4.6.0" />
|
||||
<PackageVersion Include="Microsoft.Data.SqlClient" Version="6.1.2" />
|
||||
<PackageVersion Include="Qdrant.Client" Version="1.15.1" />
|
||||
<PackageVersion Include="Testcontainers.Milvus" Version="4.14.0" />
|
||||
<PackageVersion Include="Testcontainers.MongoDB" Version="4.14.0" />
|
||||
<!-- VectorData Dependencies -->
|
||||
<PackageVersion Include="CommunityToolkit.VectorData.AzureAISearch" Version="1.0.0" />
|
||||
<PackageVersion Include="CommunityToolkit.VectorData.AzureDocumentDB" Version="1.0.0" />
|
||||
<PackageVersion Include="CommunityToolkit.VectorData.AzureCosmosDB" Version="1.0.0" />
|
||||
<PackageVersion Include="CommunityToolkit.VectorData.InMemory" Version="1.0.1" />
|
||||
<PackageVersion Include="CommunityToolkit.VectorData.PgVector" Version="1.0.0" />
|
||||
<PackageVersion Include="CommunityToolkit.VectorData.Qdrant" Version="1.0.0" />
|
||||
<PackageVersion Include="CommunityToolkit.VectorData.Redis" Version="1.0.0" />
|
||||
<PackageVersion Include="CommunityToolkit.VectorData.Weaviate" Version="1.0.0" />
|
||||
<!-- Symbols -->
|
||||
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
|
||||
<!-- Toolset -->
|
||||
@@ -242,4 +244,4 @@
|
||||
<PackageVersion Include="NAudio" Version="2.2.1" />
|
||||
<PackageVersion Include="WebRtcVadSharp" Version="1.3.2" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
{
|
||||
"solution": {
|
||||
"path": "SK-dotnet.slnx",
|
||||
"projects":
|
||||
[
|
||||
"src/VectorData/AzureAISearch/AzureAISearch.csproj",
|
||||
"src/VectorData/CosmosMongoDB/CosmosMongoDB.csproj",
|
||||
"src/VectorData/CosmosNoSql/CosmosNoSql.csproj",
|
||||
"src/VectorData/Chroma/Chroma.csproj",
|
||||
"src/VectorData/InMemory/InMemory.csproj",
|
||||
"src/VectorData/Milvus/Milvus.csproj",
|
||||
"src/VectorData/MongoDB/MongoDB.csproj",
|
||||
"src/VectorData/Pinecone/Pinecone.csproj",
|
||||
"src/VectorData/PgVector/PgVector.csproj",
|
||||
"src/VectorData/Qdrant/Qdrant.csproj",
|
||||
"src/VectorData/Redis/Redis.csproj",
|
||||
"src/VectorData/SqliteVec/SqliteVec.csproj",
|
||||
"src/VectorData/SqlServer/SqlServer.csproj",
|
||||
"src/VectorData/Weaviate/Weaviate.csproj",
|
||||
|
||||
"src/VectorData/VectorData.Abstractions/VectorData.Abstractions.csproj",
|
||||
|
||||
"test/VectorData/AzureAISearch.UnitTests/AzureAISearch.UnitTests.csproj",
|
||||
"test/VectorData/AzureAISearch.ConformanceTests/AzureAISearch.ConformanceTests.csproj",
|
||||
"test/VectorData/CosmosMongoDB.UnitTests/CosmosMongoDB.UnitTests.csproj",
|
||||
"test/VectorData/CosmosMongoDB.ConformanceTests/CosmosMongoDB.ConformanceTests.csproj",
|
||||
"test/VectorData/CosmosNoSql.UnitTests/CosmosNoSql.UnitTests.csproj",
|
||||
"test/VectorData/CosmosNoSql.ConformanceTests/CosmosNoSql.ConformanceTests.csproj",
|
||||
"test/VectorData/InMemory.UnitTests/InMemory.UnitTests.csproj",
|
||||
"test/VectorData/InMemory.ConformanceTests/InMemory.ConformanceTests.csproj",
|
||||
"test/VectorData/MongoDB.UnitTests/MongoDB.UnitTests.csproj",
|
||||
"test/VectorData/MongoDB.ConformanceTests/MongoDB.ConformanceTests.csproj",
|
||||
"test/VectorData/Pinecone.UnitTests/Pinecone.UnitTests.csproj",
|
||||
"test/VectorData/Pinecone.ConformanceTests/Pinecone.ConformanceTests.csproj",
|
||||
"test/VectorData/PgVector.UnitTests/PgVector.UnitTests.csproj",
|
||||
"test/VectorData/PgVector.ConformanceTests/PgVector.ConformanceTests.csproj",
|
||||
"test/VectorData/Qdrant.UnitTests/Qdrant.UnitTests.csproj",
|
||||
"test/VectorData/Qdrant.ConformanceTests/Qdrant.ConformanceTests.csproj",
|
||||
"test/VectorData/Redis.UnitTests/Redis.UnitTests.csproj",
|
||||
"test/VectorData/Redis.ConformanceTests/Redis.ConformanceTests.csproj",
|
||||
"test/VectorData/SqliteVec.UnitTests/SqliteVec.UnitTests.csproj",
|
||||
"test/VectorData/SqliteVec.ConformanceTests/SqliteVec.ConformanceTests.csproj",
|
||||
"test/VectorData/SqlServer.ConformanceTests/SqlServer.ConformanceTests.csproj",
|
||||
"test/VectorData/Weaviate.UnitTests/Weaviate.UnitTests.csproj",
|
||||
"test/VectorData/Weaviate.ConformanceTests/Weaviate.ConformanceTests.csproj",
|
||||
|
||||
"test/VectorData/VectorData.ConformanceTests/VectorData.ConformanceTests.csproj"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<Solution>
|
||||
<Folder Name="/Solution Items/">
|
||||
<File Path="../.editorconfig" />
|
||||
<File Path="../.github/workflows/dotnet-format.yml" />
|
||||
<File Path="../.gitignore" />
|
||||
<File Path="../nuget.config" />
|
||||
<File Path="../README.md" />
|
||||
<File Path="Directory.Build.props" />
|
||||
<File Path="Directory.Build.targets" />
|
||||
<File Path="Directory.Packages.props" />
|
||||
<File Path="docs/EXPERIMENTS.md" />
|
||||
<File Path="global.json" />
|
||||
</Folder>
|
||||
<Folder Name="/Solution Items/nuget/">
|
||||
<File Path="nuget/icon.png" />
|
||||
<File Path="nuget/nuget-package.props" />
|
||||
<File Path="nuget/NUGET.md" />
|
||||
<File Path="nuget/VECTORDATA-CONNECTORS-NUGET.md" />
|
||||
</Folder>
|
||||
<Folder Name="/src/" />
|
||||
<Folder Name="/src/VectorData/">
|
||||
<File Path="src/VectorData/Directory.Build.props" />
|
||||
<Project Path="src/VectorData/Chroma/Chroma.csproj" />
|
||||
<Project Path="src/VectorData/Milvus/Milvus.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/test/" />
|
||||
<Folder Name="/test/VectorData/">
|
||||
<Project Path="test/VectorData/Chroma.UnitTests/Chroma.UnitTests.csproj" />
|
||||
</Folder>
|
||||
</Solution>
|
||||
@@ -1,5 +1,10 @@
|
||||
# Get Started with Semantic Kernel ⚡
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Semantic Kernel is now [Microsoft Agent Framework](https://github.com/microsoft/agent-framework)! Microsoft Agent Framework (MAF) is the enterprise‑ready successor to Semantic Kernel. Microsoft Agent Framework is now available at version 1.0 as a production-ready release: stable APIs, and a commitment to long-term support. Whether you're building a single assistant or orchestrating a fleet of specialized agents, Microsoft Agent Framework 1.0 gives you enterprise-grade multi-agent orchestration, multi-provider model support, and cross-runtime interoperability via A2A and MCP.
|
||||
>
|
||||
> Learn more about Semantic Kernel and Agent Framework here: [Semantic Kernel and Microsoft Agent Framework on the Agent Framework blog](https://devblogs.microsoft.com/agent-framework/semantic-kernel-and-microsoft-agent-framework/), and try out the [Semantic Kernel migration guide](https://learn.microsoft.com/en-us/agent-framework/migration-guide/from-semantic-kernel).
|
||||
|
||||
## OpenAI / Azure OpenAI API keys
|
||||
|
||||
To run the LLM prompts and semantic functions in the examples below, make sure
|
||||
|
||||
@@ -121,24 +121,6 @@
|
||||
<Project Path="src/Connectors/Connectors.OpenAI.UnitTests/Connectors.OpenAI.UnitTests.csproj" />
|
||||
<Project Path="src/Connectors/Connectors.OpenAI/Connectors.OpenAI.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/src/VectorData/">
|
||||
<File Path="src/VectorData/Directory.Build.props" />
|
||||
<Project Path="src/VectorData/AzureAISearch/AzureAISearch.csproj" />
|
||||
<Project Path="src/VectorData/Chroma/Chroma.csproj" />
|
||||
<Project Path="src/VectorData/CosmosMongoDB/CosmosMongoDB.csproj" />
|
||||
<Project Path="src/VectorData/CosmosNoSql/CosmosNoSql.csproj" />
|
||||
<Project Path="src/VectorData/InMemory/InMemory.csproj" />
|
||||
<Project Path="src/VectorData/Milvus/Milvus.csproj" />
|
||||
<Project Path="src/VectorData/MongoDB/MongoDB.csproj" />
|
||||
<Project Path="src/VectorData/PgVector/PgVector.csproj" />
|
||||
<Project Path="src/VectorData/Pinecone/Pinecone.csproj" />
|
||||
<Project Path="src/VectorData/Qdrant/Qdrant.csproj" />
|
||||
<Project Path="src/VectorData/Redis/Redis.csproj" />
|
||||
<Project Path="src/VectorData/SqliteVec/SqliteVec.csproj" />
|
||||
<Project Path="src/VectorData/SqlServer/SqlServer.csproj" />
|
||||
<Project Path="src/VectorData/VectorData.Abstractions/VectorData.Abstractions.csproj" />
|
||||
<Project Path="src/VectorData/Weaviate/Weaviate.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/src/experimental/">
|
||||
<Project Path="src/Experimental/Orchestration.Flow.IntegrationTests/Experimental.Orchestration.Flow.IntegrationTests.csproj" />
|
||||
<Project Path="src/Experimental/Orchestration.Flow.UnitTests/Experimental.Orchestration.Flow.UnitTests.csproj" />
|
||||
@@ -292,33 +274,4 @@
|
||||
<Project Path="src/Plugins/Plugins.UnitTests/Plugins.UnitTests.csproj" />
|
||||
<Project Path="src/Plugins/Plugins.Web/Plugins.Web.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/test/" />
|
||||
<Folder Name="/test/VectorData/">
|
||||
<Project Path="test/VectorData/AzureAISearch.ConformanceTests/AzureAISearch.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/AzureAISearch.UnitTests/AzureAISearch.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/Chroma.UnitTests/Chroma.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/CosmosMongoDB.ConformanceTests/CosmosMongoDB.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/CosmosMongoDB.UnitTests/CosmosMongoDB.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/CosmosNoSql.ConformanceTests/CosmosNoSql.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/CosmosNoSql.UnitTests/CosmosNoSql.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/InMemory.ConformanceTests/InMemory.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/InMemory.UnitTests/InMemory.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/MongoDB.ConformanceTests/MongoDB.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/MongoDB.UnitTests/MongoDB.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/PgVector.ConformanceTests/PgVector.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/PgVector.UnitTests/PgVector.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/Pinecone.ConformanceTests/Pinecone.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/Pinecone.UnitTests/Pinecone.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/Qdrant.ConformanceTests/Qdrant.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/Qdrant.UnitTests/Qdrant.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/Redis.ConformanceTests/Redis.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/Redis.UnitTests/Redis.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/SqliteVec.ConformanceTests/SqliteVec.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/SqliteVec.UnitTests/SqliteVec.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/SqlServer.ConformanceTests/SqlServer.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/VectorData.ConformanceTests/VectorData.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/VectorData.UnitTests/VectorData.UnitTests.csproj" />
|
||||
<Project Path="test/VectorData/Weaviate.ConformanceTests/Weaviate.ConformanceTests.csproj" />
|
||||
<Project Path="test/VectorData/Weaviate.UnitTests/Weaviate.UnitTests.csproj" />
|
||||
</Folder>
|
||||
</Solution>
|
||||
|
||||
@@ -32,22 +32,6 @@
|
||||
"src\\Connectors\\Connectors.Onnx\\Connectors.Onnx.csproj",
|
||||
"src\\Connectors\\Connectors.OpenAI\\Connectors.OpenAI.csproj",
|
||||
|
||||
"src\\VectorData\\AzureAISearch\\AzureAISearch.csproj",
|
||||
"src\\VectorData\\Chroma\\Chroma.csproj",
|
||||
"src\\VectorData\\CosmosMongoDB\\CosmosMongoDB.csproj",
|
||||
"src\\VectorData\\CosmosNoSql\\CosmosNoSql.csproj",
|
||||
"src\\VectorData\\InMemory\\InMemory.csproj",
|
||||
"src\\VectorData\\Milvus\\Milvus.csproj",
|
||||
"src\\VectorData\\MongoDB\\MongoDB.csproj",
|
||||
"src\\VectorData\\PgVector\\PgVector.csproj",
|
||||
"src\\VectorData\\Pinecone\\Pinecone.csproj",
|
||||
"src\\VectorData\\Qdrant\\Qdrant.csproj",
|
||||
"src\\VectorData\\Redis\\Redis.csproj",
|
||||
"src\\VectorData\\SqliteVec\\SqliteVec.csproj",
|
||||
"src\\VectorData\\SqlServer\\SqlServer.csproj",
|
||||
"src\\VectorData\\VectorData.Abstractions\\VectorData.Abstractions.csproj",
|
||||
"src\\VectorData\\Weaviate\\Weaviate.csproj",
|
||||
|
||||
"src\\Experimental\\Orchestration.Flow\\Experimental.Orchestration.Flow.csproj",
|
||||
|
||||
"src\\Experimental\\Process.Abstractions\\Process.Abstractions.csproj",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "10.0.100",
|
||||
"version": "10.0.303",
|
||||
"rollForward": "major",
|
||||
"allowPrerelease": false
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
|
||||
<packageSourceMapping>
|
||||
<packageSource key="nuget.org">
|
||||
<package pattern="*" />
|
||||
</packageSource>
|
||||
</packageSourceMapping>
|
||||
|
||||
</configuration>
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<!-- Central version prefix - applies to all nuget packages. -->
|
||||
<VersionPrefix>1.74.0</VersionPrefix>
|
||||
<VersionPrefix>1.80.1</VersionPrefix>
|
||||
<PackageVersion Condition="'$(VersionSuffix)' != ''">$(VersionPrefix)-$(VersionSuffix)</PackageVersion>
|
||||
<PackageVersion Condition="'$(VersionSuffix)' == ''">$(VersionPrefix)</PackageVersion>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<IsPackable>true</IsPackable>
|
||||
|
||||
<!-- Package validation. Baseline Version should be the latest version available on NuGet. -->
|
||||
<PackageValidationBaselineVersion>1.73.0</PackageValidationBaselineVersion>
|
||||
<PackageValidationBaselineVersion>1.80.0</PackageValidationBaselineVersion>
|
||||
<!-- Validate assembly attributes only for Publish builds -->
|
||||
<NoWarn Condition="'$(Configuration)' != 'Publish'">$(NoWarn);CP0003</NoWarn>
|
||||
<!-- Do not validate reference assemblies -->
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.AzureAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Workflows" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
+2
-2
@@ -79,13 +79,13 @@ async Task AFConcurrentAgentWorkflow()
|
||||
var spanishAgent = GetAFTranslationAgent("Spanish", client);
|
||||
var concurrentAgentWorkflow = AgentWorkflowBuilder.BuildConcurrent([frenchAgent, spanishAgent]);
|
||||
|
||||
await using StreamingRun run = await InProcessExecution.StreamAsync(concurrentAgentWorkflow, "Hello, world!");
|
||||
await using StreamingRun run = await InProcessExecution.RunStreamingAsync(concurrentAgentWorkflow, "Hello, world!");
|
||||
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
|
||||
|
||||
string? lastExecutorId = null;
|
||||
await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (evt is AgentRunUpdateEvent e)
|
||||
if (evt is AgentResponseUpdateEvent e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(e.Update.Text))
|
||||
{
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.AzureAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Workflows" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
+2
-2
@@ -82,13 +82,13 @@ async Task AFSequentialAgentWorkflow()
|
||||
var sequentialAgentWorkflow = AgentWorkflowBuilder.BuildSequential(
|
||||
[frenchAgent, spanishAgent, englishAgent]);
|
||||
|
||||
await using StreamingRun run = await InProcessExecution.StreamAsync(sequentialAgentWorkflow, "Hello, world!");
|
||||
await using StreamingRun run = await InProcessExecution.RunStreamingAsync(sequentialAgentWorkflow, "Hello, world!");
|
||||
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
|
||||
|
||||
string? lastExecutorId = null;
|
||||
await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (evt is AgentRunUpdateEvent e)
|
||||
if (evt is AgentResponseUpdateEvent e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(e.Update.Text))
|
||||
{
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.AzureAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Workflows" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
+4
-2
@@ -1,5 +1,7 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
#pragma warning disable MAAIW001 // Experimental: HandoffWorkflowBuilder
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Text.Json;
|
||||
using Azure.AI.OpenAI;
|
||||
@@ -207,13 +209,13 @@ async Task AFHandoffAgentWorkflow()
|
||||
Console.WriteLine($"User: {query}");
|
||||
messages.Add(new(ChatRole.User, query));
|
||||
|
||||
await using var run = await InProcessExecution.StreamAsync(handoffAgentWorkflow, messages);
|
||||
await using var run = await InProcessExecution.RunStreamingAsync(handoffAgentWorkflow, messages);
|
||||
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
|
||||
|
||||
string? lastExecutorId = null;
|
||||
await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (evt is AgentRunUpdateEvent e)
|
||||
if (evt is AgentResponseUpdateEvent e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(e.Update.Text) && e.Update.Contents.Count == 0)
|
||||
{
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.AzureAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Foundry" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
@@ -67,7 +68,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
@@ -80,9 +81,9 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
if (thread is ChatClientAgentSession chatSession)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId);
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatSession.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
@@ -91,29 +92,23 @@ async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var azureAgentClient = new PersistentAgentsClient(azureEndpoint, new AzureCliCredential());
|
||||
// AF 1.0: Use AIProjectClient.AsAIAgent() from Microsoft.Agents.AI.Foundry
|
||||
var projectClient = new AIProjectClient(new Uri(azureEndpoint), new AzureCliCredential());
|
||||
|
||||
var agent = await azureAgentClient.CreateAIAgentAsync(
|
||||
var agent = projectClient.AsAIAgent(
|
||||
deploymentName,
|
||||
name: "GenerateStory",
|
||||
instructions: "You are good at telling jokes.");
|
||||
instructions: "You are good at telling jokes.",
|
||||
name: "GenerateStory");
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.AzureAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Foundry" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using System.ComponentModel;
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
@@ -85,7 +86,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { Tools = [AIFunctionFactory.Create(GetWeather)] });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
@@ -98,9 +99,9 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
if (thread is ChatClientAgentSession chatSession)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId);
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatSession.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
@@ -109,26 +110,22 @@ async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var azureAgentClient = new PersistentAgentsClient(azureEndpoint, new AzureCliCredential());
|
||||
var agent = new AIProjectClient(new Uri(azureEndpoint), new AzureCliCredential())
|
||||
.AsAIAgent(model: deploymentName,
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
var agent = await azureAgentClient.CreateAIAgentAsync(deploymentName, instructions: "Answer questions about the menu");
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { Tools = [AIFunctionFactory.Create(GetWeather)] });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
// No cleanup needed - non-hosted path doesn't create server-side resources.
|
||||
}
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.AzureAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Foundry" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
+14
-20
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
@@ -90,7 +91,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
Console.WriteLine(result);
|
||||
@@ -103,9 +104,9 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
// Clean up
|
||||
var azureAgentClient = serviceProvider.GetRequiredService<PersistentAgentsClient>();
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
if (thread is ChatClientAgentSession chatSession)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId);
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatSession.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
@@ -115,36 +116,29 @@ async Task AFAgentAsync()
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton((sp) => new PersistentAgentsClient(azureEndpoint, new AzureCliCredential()));
|
||||
serviceCollection.AddSingleton((sp) => new AIProjectClient(new Uri(azureEndpoint), new AzureCliCredential()));
|
||||
serviceCollection.AddTransient<AIAgent>((sp) =>
|
||||
{
|
||||
var azureAgentClient = sp.GetRequiredService<PersistentAgentsClient>();
|
||||
|
||||
return azureAgentClient.CreateAIAgent(
|
||||
deploymentName,
|
||||
name: "GenerateStory",
|
||||
instructions: "You are good at telling jokes.");
|
||||
var client = sp.GetRequiredService<AIProjectClient>();
|
||||
return client.AsAIAgent(
|
||||
deploymentName,
|
||||
instructions: "You are good at telling jokes.",
|
||||
name: "GenerateStory");
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var session = await agent.CreateSessionAsync();
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
var result = await agent.RunAsync(userInput, session);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread))
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
var azureAgentClient = serviceProvider.GetRequiredService<PersistentAgentsClient>();
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
// No cleanup needed - non-hosted path doesn't create server-side resources.
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.AzureAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Foundry" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
+12
-55
@@ -2,6 +2,7 @@
|
||||
|
||||
using System.Text;
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
@@ -76,7 +77,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
Console.WriteLine(result);
|
||||
@@ -124,9 +125,9 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
if (thread is ChatClientAgentSession chatSession)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId);
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatSession.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
@@ -135,59 +136,15 @@ async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var azureAgentClient = new PersistentAgentsClient(azureEndpoint, new AzureCliCredential());
|
||||
var agent = await azureAgentClient.CreateAIAgentAsync(deploymentName, tools: [new CodeInterpreterToolDefinition()]);
|
||||
var thread = agent.GetNewThread();
|
||||
// Note: Code interpreter via hosted APIs requires versioned Foundry Agents.
|
||||
// This sample creates a basic agent without code interpreter capabilities.
|
||||
var agent = new AIProjectClient(new Uri(azureEndpoint), new AzureCliCredential())
|
||||
.AsAIAgent(deploymentName, instructions: "You are a helpful assistant with code execution capabilities.");
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
var session = await agent.CreateSessionAsync();
|
||||
|
||||
var result = await agent.RunAsync(userInput, session);
|
||||
Console.WriteLine(result);
|
||||
|
||||
// Extracts via breaking glass the code generated by code interpreter tool
|
||||
var chatResponse = result.RawRepresentation as ChatResponse;
|
||||
StringBuilder generatedCode = new();
|
||||
foreach (object? updateRawRepresentation in chatResponse?.RawRepresentation as IEnumerable<object?> ?? [])
|
||||
{
|
||||
// To capture the code interpreter input we need to break glass all the updates raw representations, to check for the RunStepDetailsUpdate type and
|
||||
// get the CodeInterpreterInput property which contains the generated code.
|
||||
// Note: Similar logic would needed for each individual update if used in the agent.RunStreamingAsync streaming API to aggregate or yield the generated code.
|
||||
if (updateRawRepresentation is RunStepDetailsUpdate update && update.CodeInterpreterInput is not null)
|
||||
{
|
||||
generatedCode.Append(update.CodeInterpreterInput);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(generatedCode.ToString()))
|
||||
{
|
||||
Console.WriteLine($"\n# {chatResponse?.Messages[0].Role}:Generated Code:\n{generatedCode}");
|
||||
}
|
||||
|
||||
// Update the citations
|
||||
foreach (var textContent in result.Messages[0].Contents.OfType<Microsoft.Extensions.AI.TextContent>())
|
||||
{
|
||||
foreach (var annotation in textContent.Annotations ?? [])
|
||||
{
|
||||
if (annotation is CitationAnnotation citation)
|
||||
{
|
||||
if (citation.Url is null)
|
||||
{
|
||||
Console.WriteLine($" [{citation.GetType().Name}] {citation.Snippet}: File #{citation.FileId}");
|
||||
}
|
||||
|
||||
foreach (var region in citation.AnnotatedRegions ?? [])
|
||||
{
|
||||
if (region is TextSpanAnnotatedRegion textSpanRegion)
|
||||
{
|
||||
Console.WriteLine($"\n[TextSpan Region] {textSpanRegion.StartIndex}-{textSpanRegion.EndIndex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
// No cleanup needed - non-hosted path doesn't create server-side resources.
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ using Microsoft.Agents.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
@@ -65,7 +65,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
@@ -83,9 +83,9 @@ async Task AFAgent()
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName)
|
||||
.CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes.");
|
||||
.AsAIAgent(name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
|
||||
@@ -6,7 +6,7 @@ using Azure.Identity;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using OpenAI;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
@@ -73,7 +73,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
async Task AFAgent()
|
||||
{
|
||||
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName)
|
||||
.CreateAIAgent(instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
.AsAIAgent(instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
Console.WriteLine("\n=== AF Agent Response ===\n");
|
||||
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@ using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using OpenAI;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
@@ -72,7 +72,7 @@ async Task AFAgent()
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient<AIAgent>((sp) => new AzureOpenAIClient(new(endpoint), new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes."));
|
||||
.AsAIAgent(name: "Joker", instructions: "You are good at telling jokes."));
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
+2
-2
@@ -9,7 +9,7 @@ using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Plugins.OpenApi;
|
||||
using OpenAI;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
@@ -59,7 +59,7 @@ async Task AFAgent()
|
||||
new Uri(endpoint),
|
||||
new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.CreateAIAgent(instructions: "You are a helpful assistant", tools: tools);
|
||||
.AsAIAgent(instructions: "You are a helpful assistant", tools: tools);
|
||||
|
||||
// Run the agent with the OpenAPI function tools.
|
||||
Console.WriteLine(await agent.RunAsync("Please list the names, colors and descriptions of all the labels available in the microsoft/agent-framework repository on github."));
|
||||
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
-120
@@ -1,120 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Assistants;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgent();
|
||||
await SKAgent_As_AFAgent();
|
||||
await AFAgent();
|
||||
|
||||
async Task SKAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
var _ = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
|
||||
var assistantsClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient();
|
||||
|
||||
// Define the assistant
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
// Create the agent
|
||||
OpenAIAssistantAgent agent = new(assistant, assistantsClient);
|
||||
|
||||
// Create a thread for the agent conversation.
|
||||
var thread = new OpenAIAssistantAgentThread(assistantsClient);
|
||||
var settings = new OpenAIPromptExecutionSettings() { MaxTokens = 1000 };
|
||||
var agentOptions = new OpenAIAssistantAgentInvokeOptions() { KernelArguments = new(settings) };
|
||||
|
||||
await foreach (var result in agent.InvokeAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.InvokeStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update.Message);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
var _ = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
|
||||
var assistantsClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient();
|
||||
|
||||
// Define the assistant
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
// Create the agent
|
||||
OpenAIAssistantAgent skAgent = new(assistant, assistantsClient);
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantsClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var assistantClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient();
|
||||
|
||||
var agent = await assistantClient.CreateAIAgentAsync(deploymentName, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
-147
@@ -1,147 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Assistants;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "What is the weather like in Amsterdam?";
|
||||
|
||||
[KernelFunction]
|
||||
[Description("Get the weather for a given location.")]
|
||||
static string GetWeather([Description("The location to get the weather for.")] string location)
|
||||
=> $"The weather in {location} is cloudy with a high of 15°C.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgent();
|
||||
await SKAgent_As_AFAgent();
|
||||
await AFAgent();
|
||||
|
||||
async Task SKAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var builder = Kernel.CreateBuilder();
|
||||
var assistantsClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient();
|
||||
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName,
|
||||
instructions: "You are a helpful assistant");
|
||||
|
||||
OpenAIAssistantAgent agent = new(assistant, assistantsClient)
|
||||
{
|
||||
Kernel = builder.Build(),
|
||||
Arguments = new KernelArguments(new OpenAIPromptExecutionSettings()
|
||||
{
|
||||
MaxTokens = 1000,
|
||||
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
|
||||
}),
|
||||
};
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
agent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
// Create a thread for the agent conversation.
|
||||
var thread = new OpenAIAssistantAgentThread(assistantsClient);
|
||||
|
||||
await foreach (var result in agent.InvokeAsync(userInput, thread))
|
||||
{
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.InvokeStreamingAsync(userInput, thread))
|
||||
{
|
||||
Console.Write(update.Message);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var builder = Kernel.CreateBuilder();
|
||||
var assistantsClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient();
|
||||
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName,
|
||||
instructions: "You are a helpful assistant");
|
||||
|
||||
OpenAIAssistantAgent skAgent = new(assistant, assistantsClient)
|
||||
{
|
||||
Kernel = builder.Build(),
|
||||
Arguments = new KernelArguments(new OpenAIPromptExecutionSettings()
|
||||
{
|
||||
MaxTokens = 1000,
|
||||
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
|
||||
}),
|
||||
};
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
skAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantsClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var assistantClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient();
|
||||
|
||||
var agent = await assistantClient.CreateAIAgentAsync(deploymentName,
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
-144
@@ -1,144 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Assistants;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgent();
|
||||
await SKAgent_As_AFAgent();
|
||||
await AFAgent();
|
||||
|
||||
async Task SKAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton((sp) => new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient());
|
||||
serviceCollection.AddKernel().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
serviceCollection.AddTransient((sp) =>
|
||||
{
|
||||
var assistantsClient = sp.GetRequiredService<AssistantClient>();
|
||||
|
||||
Assistant assistant = assistantsClient.CreateAssistant(deploymentName, new() { Name = "Joker", Instructions = "You are good at telling jokes." });
|
||||
|
||||
return new OpenAIAssistantAgent(assistant, assistantsClient);
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<OpenAIAssistantAgent>();
|
||||
|
||||
// Create a thread for the agent conversation.
|
||||
var assistantsClient = serviceProvider.GetRequiredService<AssistantClient>();
|
||||
var thread = new OpenAIAssistantAgentThread(assistantsClient);
|
||||
var settings = new OpenAIPromptExecutionSettings() { MaxTokens = 1000 };
|
||||
var agentOptions = new OpenAIAssistantAgentInvokeOptions() { KernelArguments = new(settings) };
|
||||
|
||||
await foreach (var result in agent.InvokeAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.InvokeStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update.Message);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton((sp) => new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient());
|
||||
serviceCollection.AddKernel().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
serviceCollection.AddTransient((sp) =>
|
||||
{
|
||||
var assistantsClient = sp.GetRequiredService<AssistantClient>();
|
||||
|
||||
Assistant assistant = assistantsClient.CreateAssistant(deploymentName, new() { Name = "Joker", Instructions = "You are good at telling jokes." });
|
||||
|
||||
return new OpenAIAssistantAgent(assistant, assistantsClient);
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var skAgent = serviceProvider.GetRequiredService<OpenAIAssistantAgent>();
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
var assistantClient = serviceProvider.GetRequiredService<AssistantClient>();
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton((sp) => new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient());
|
||||
serviceCollection.AddTransient<AIAgent>((sp) =>
|
||||
{
|
||||
var assistantClient = sp.GetRequiredService<AssistantClient>();
|
||||
|
||||
return assistantClient.CreateAIAgent(deploymentName, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
var assistantClient = serviceProvider.GetRequiredService<AssistantClient>();
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
-196
@@ -1,196 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Text;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Assistants;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "Create a python code file using the code interpreter tool with a code ready to determine the values in the Fibonacci sequence that are less then the value of 101";
|
||||
|
||||
var assistantsClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient();
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgent();
|
||||
await SKAgent_As_AFAgent();
|
||||
await AFAgent();
|
||||
|
||||
async Task SKAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
var _ = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
|
||||
// Define the assistant
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName, enableCodeInterpreter: true);
|
||||
|
||||
// Create the agent
|
||||
OpenAIAssistantAgent agent = new(assistant, assistantsClient);
|
||||
|
||||
// Create a thread for the agent conversation.
|
||||
var thread = new OpenAIAssistantAgentThread(assistantsClient);
|
||||
|
||||
// Respond to user input
|
||||
await foreach (var content in agent.InvokeAsync(userInput, thread))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(content.Message.Content))
|
||||
{
|
||||
bool isCode = content.Message.Metadata?.ContainsKey(OpenAIAssistantAgent.CodeInterpreterMetadataKey) ?? false;
|
||||
Console.WriteLine($"\n# {content.Message.Role}{(isCode ? "\n# Generated Code:\n" : ":")}{content.Message.Content}");
|
||||
}
|
||||
|
||||
// Check for the citations
|
||||
foreach (var item in content.Message.Items)
|
||||
{
|
||||
// Process each item in the message
|
||||
if (item is AnnotationContent annotation)
|
||||
{
|
||||
if (annotation.Kind != AnnotationKind.UrlCitation)
|
||||
{
|
||||
Console.WriteLine($" [{item.GetType().Name}] {annotation.Label}: File #{annotation.ReferenceId}");
|
||||
}
|
||||
}
|
||||
else if (item is FileReferenceContent fileReference)
|
||||
{
|
||||
Console.WriteLine($" [{item.GetType().Name}] File #{fileReference.FileId}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
var _ = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
|
||||
// Define the assistant
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName, enableCodeInterpreter: true);
|
||||
|
||||
// Create the agent
|
||||
OpenAIAssistantAgent skAgent = new(assistant, assistantsClient);
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
Console.WriteLine(result);
|
||||
|
||||
// Extracts via breaking glass the code generated by code interpreter tool
|
||||
var chatResponse = result.RawRepresentation as ChatResponse;
|
||||
StringBuilder generatedCode = new();
|
||||
foreach (object? updateRawRepresentation in chatResponse?.RawRepresentation as IEnumerable<object?> ?? [])
|
||||
{
|
||||
if (updateRawRepresentation is RunStepDetailsUpdate update && update.CodeInterpreterInput is not null)
|
||||
{
|
||||
generatedCode.Append(update.CodeInterpreterInput);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(generatedCode.ToString()))
|
||||
{
|
||||
Console.WriteLine($"\n# {chatResponse?.Messages[0].Role}:Generated Code:\n{generatedCode}");
|
||||
}
|
||||
|
||||
// Check for the citations
|
||||
foreach (var textContent in result.Messages[0].Contents.OfType<Microsoft.Extensions.AI.TextContent>())
|
||||
{
|
||||
foreach (var annotation in textContent.Annotations ?? [])
|
||||
{
|
||||
if (annotation is CitationAnnotation citation)
|
||||
{
|
||||
if (citation.Url is null)
|
||||
{
|
||||
Console.WriteLine($" [{citation.GetType().Name}] {citation.Snippet}: File #{citation.FileId}");
|
||||
}
|
||||
|
||||
foreach (var region in citation.AnnotatedRegions ?? [])
|
||||
{
|
||||
if (region is TextSpanAnnotatedRegion textSpanRegion)
|
||||
{
|
||||
Console.WriteLine($"\n[TextSpan Region] {textSpanRegion.StartIndex}-{textSpanRegion.EndIndex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantsClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = await assistantsClient.CreateAIAgentAsync(deploymentName, tools: [new HostedCodeInterpreterTool()]);
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
Console.WriteLine(result);
|
||||
|
||||
// Extracts via breaking glass the code generated by code interpreter tool
|
||||
var chatResponse = result.RawRepresentation as ChatResponse;
|
||||
StringBuilder generatedCode = new();
|
||||
foreach (object? updateRawRepresentation in chatResponse?.RawRepresentation as IEnumerable<object?> ?? [])
|
||||
{
|
||||
if (updateRawRepresentation is RunStepDetailsUpdate update && update.CodeInterpreterInput is not null)
|
||||
{
|
||||
generatedCode.Append(update.CodeInterpreterInput);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(generatedCode.ToString()))
|
||||
{
|
||||
Console.WriteLine($"\n# {chatResponse?.Messages[0].Role}:Generated Code:\n{generatedCode}");
|
||||
}
|
||||
|
||||
// Check for the citations
|
||||
foreach (var textContent in result.Messages[0].Contents.OfType<Microsoft.Extensions.AI.TextContent>())
|
||||
{
|
||||
foreach (var annotation in textContent.Annotations ?? [])
|
||||
{
|
||||
if (annotation is CitationAnnotation citation)
|
||||
{
|
||||
if (citation.Url is null)
|
||||
{
|
||||
Console.WriteLine($" [{citation.GetType().Name}] {citation.Snippet}: File #{citation.FileId}");
|
||||
}
|
||||
|
||||
foreach (var region in citation.AnnotatedRegions ?? [])
|
||||
{
|
||||
if (region is TextSpanAnnotatedRegion textSpanRegion)
|
||||
{
|
||||
Console.WriteLine($"\n[TextSpan Region] {textSpanRegion.StartIndex}-{textSpanRegion.EndIndex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantsClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
+7
-7
@@ -5,7 +5,7 @@ using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
@@ -66,7 +66,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
@@ -84,17 +84,17 @@ async Task AFAgentAsync()
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient().AsIChatClient(deploymentName)
|
||||
.CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes.");
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(model: deploymentName, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
+7
-7
@@ -7,7 +7,7 @@ using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
using OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
@@ -134,7 +134,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new()
|
||||
{
|
||||
MaxOutputTokens = 8000,
|
||||
@@ -180,10 +180,10 @@ async Task AFAgentAsync()
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient().AsIChatClient(deploymentName)
|
||||
.CreateAIAgent(name: "Thinker", instructions: "You are good at thinking hard before answering.");
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(model: deploymentName, name: "Thinker", instructions: "You are good at thinking hard before answering.");
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new()
|
||||
{
|
||||
MaxOutputTokens = 8000,
|
||||
@@ -194,7 +194,7 @@ async Task AFAgentAsync()
|
||||
}
|
||||
});
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
|
||||
// Retrieve the thinking as a full text block requires flattening multiple TextReasoningContents from multiple messages content lists.
|
||||
string assistantThinking = string.Join("\n", result.Messages
|
||||
@@ -207,7 +207,7 @@ async Task AFAgentAsync()
|
||||
Console.WriteLine($"Assistant: \n{assistantText}\n---\n");
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
var thinkingContents = update.Contents
|
||||
.OfType<TextReasoningContent>()
|
||||
|
||||
+3
-3
@@ -6,7 +6,7 @@ using Azure.Identity;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
@@ -66,8 +66,8 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient().AsIChatClient(deploymentName)
|
||||
.CreateAIAgent(instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(model: deploymentName, instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
Console.WriteLine("\n=== AF Agent Response ===\n");
|
||||
|
||||
|
||||
+3
-3
@@ -6,7 +6,7 @@ using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
@@ -71,8 +71,8 @@ async Task AFAgentAsync()
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient<AIAgent>((sp) => new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient().AsIChatClient(deploymentName)
|
||||
.CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes."));
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(model: deploymentName, name: "Joker", instructions: "You are good at telling jokes."));
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
@@ -5,6 +5,7 @@ using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o";
|
||||
@@ -64,7 +65,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
@@ -83,9 +84,9 @@ async Task AFAgentAsync()
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new OpenAIClient(apiKey).GetChatClient(model)
|
||||
.CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes.");
|
||||
.AsAIAgent(name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
|
||||
@@ -6,6 +6,7 @@ using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using OpenAI;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o";
|
||||
@@ -65,7 +66,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
var agent = skAgent.AsAIAgent();
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
@@ -86,7 +87,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
var agent = new OpenAIClient(apiKey).GetChatClient(model).CreateAIAgent(
|
||||
var agent = new OpenAIClient(apiKey).GetChatClient(model).AsAIAgent(
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using OpenAI;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o";
|
||||
@@ -70,7 +71,7 @@ async Task AFAgentAsync()
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient<AIAgent>((sp) => new OpenAIClient(apiKey)
|
||||
.GetChatClient(model)
|
||||
.CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes."));
|
||||
.AsAIAgent(name: "Joker", instructions: "You are good at telling jokes."));
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,116 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Assistants;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var assistantsClient = new AssistantClient(apiKey);
|
||||
|
||||
// Define the assistant
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(model, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
// Create the agent
|
||||
OpenAIAssistantAgent agent = new(assistant, assistantsClient);
|
||||
|
||||
// Create a thread for the agent conversation.
|
||||
var thread = new OpenAIAssistantAgentThread(assistantsClient);
|
||||
var settings = new OpenAIPromptExecutionSettings() { MaxTokens = 1000 };
|
||||
var agentOptions = new OpenAIAssistantAgentInvokeOptions() { KernelArguments = new(settings) };
|
||||
|
||||
await foreach (var result in agent.InvokeAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.InvokeStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update.Message);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
// Example of Semantic Kernel Agent code converted as an Agent Framework Agent
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var assistantsClient = new AssistantClient(apiKey);
|
||||
|
||||
// Define the assistant
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(model, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
// Create the agent
|
||||
OpenAIAssistantAgent agent = new(assistant, assistantsClient);
|
||||
|
||||
var afAgent = agent.AsAIAgent();
|
||||
|
||||
var thread = afAgent.GetNewThread();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await afAgent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in afAgent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantsClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var assistantClient = new AssistantClient(apiKey);
|
||||
|
||||
var agent = await assistantClient.CreateAIAgentAsync(model, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,145 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Assistants;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o";
|
||||
var userInput = "What is the weather like in Amsterdam?";
|
||||
|
||||
[KernelFunction]
|
||||
[Description("Get the weather for a given location.")]
|
||||
static string GetWeather([Description("The location to get the weather for.")] string location)
|
||||
=> $"The weather in {location} is cloudy with a high of 15°C.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var builder = Kernel.CreateBuilder();
|
||||
var assistantsClient = new AssistantClient(apiKey);
|
||||
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(model,
|
||||
instructions: "You are a helpful assistant");
|
||||
|
||||
OpenAIAssistantAgent agent = new(assistant, assistantsClient)
|
||||
{
|
||||
Kernel = builder.Build(),
|
||||
Arguments = new KernelArguments(new OpenAIPromptExecutionSettings()
|
||||
{
|
||||
MaxTokens = 1000,
|
||||
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
|
||||
}),
|
||||
};
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
agent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
// Create a thread for the agent conversation.
|
||||
var thread = new OpenAIAssistantAgentThread(assistantsClient);
|
||||
|
||||
await foreach (var result in agent.InvokeAsync(userInput, thread))
|
||||
{
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.InvokeStreamingAsync(userInput, thread))
|
||||
{
|
||||
Console.Write(update.Message);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var builder = Kernel.CreateBuilder();
|
||||
var assistantsClient = new AssistantClient(apiKey);
|
||||
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(model,
|
||||
instructions: "You are a helpful assistant");
|
||||
|
||||
OpenAIAssistantAgent skAgent = new(assistant, assistantsClient)
|
||||
{
|
||||
Kernel = builder.Build(),
|
||||
Arguments = new KernelArguments(new OpenAIPromptExecutionSettings()
|
||||
{
|
||||
MaxTokens = 1000,
|
||||
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
|
||||
}),
|
||||
};
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
skAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantsClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var assistantClient = new AssistantClient(apiKey);
|
||||
|
||||
var agent = await assistantClient.CreateAIAgentAsync(model,
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
-142
@@ -1,142 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Assistants;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton((sp) => new AssistantClient(apiKey));
|
||||
serviceCollection.AddKernel().AddOpenAIChatClient(model, apiKey);
|
||||
serviceCollection.AddTransient((sp) =>
|
||||
{
|
||||
var assistantsClient = sp.GetRequiredService<AssistantClient>();
|
||||
|
||||
Assistant assistant = assistantsClient.CreateAssistant(model, new() { Name = "Joker", Instructions = "You are good at telling jokes." });
|
||||
|
||||
return new OpenAIAssistantAgent(assistant, assistantsClient);
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<OpenAIAssistantAgent>();
|
||||
|
||||
// Create a thread for the agent conversation.
|
||||
var assistantsClient = serviceProvider.GetRequiredService<AssistantClient>();
|
||||
var thread = new OpenAIAssistantAgentThread(assistantsClient);
|
||||
var settings = new OpenAIPromptExecutionSettings() { MaxTokens = 1000 };
|
||||
var agentOptions = new OpenAIAssistantAgentInvokeOptions() { KernelArguments = new(settings) };
|
||||
|
||||
await foreach (var result in agent.InvokeAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.InvokeStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update.Message);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton((sp) => new AssistantClient(apiKey));
|
||||
serviceCollection.AddKernel().AddOpenAIChatClient(model, apiKey);
|
||||
serviceCollection.AddTransient((sp) =>
|
||||
{
|
||||
var assistantsClient = sp.GetRequiredService<AssistantClient>();
|
||||
|
||||
Assistant assistant = assistantsClient.CreateAssistant(model, new() { Name = "Joker", Instructions = "You are good at telling jokes." });
|
||||
|
||||
return new OpenAIAssistantAgent(assistant, assistantsClient);
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var skAgent = serviceProvider.GetRequiredService<OpenAIAssistantAgent>();
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
var assistantClient = serviceProvider.GetRequiredService<AssistantClient>();
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton((sp) => new AssistantClient(apiKey));
|
||||
serviceCollection.AddTransient((sp) =>
|
||||
{
|
||||
var assistantClient = sp.GetRequiredService<AssistantClient>();
|
||||
|
||||
return assistantClient.CreateAIAgent(model, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
var assistantClient = serviceProvider.GetRequiredService<AssistantClient>();
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
-192
@@ -1,192 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Text;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Assistants;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o";
|
||||
var userInput = "Create a python code file using the code interpreter tool with a code ready to determine the values in the Fibonacci sequence that are less then the value of 101";
|
||||
|
||||
var assistantsClient = new AssistantClient(apiKey);
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
// Define the assistant
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(model, enableCodeInterpreter: true);
|
||||
|
||||
// Create the agent
|
||||
OpenAIAssistantAgent agent = new(assistant, assistantsClient);
|
||||
|
||||
// Create a thread for the agent conversation.
|
||||
var thread = new OpenAIAssistantAgentThread(assistantsClient);
|
||||
|
||||
// Respond to user input
|
||||
await foreach (var content in agent.InvokeAsync(userInput, thread))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(content.Message.Content))
|
||||
{
|
||||
bool isCode = content.Message.Metadata?.ContainsKey(OpenAIAssistantAgent.CodeInterpreterMetadataKey) ?? false;
|
||||
Console.WriteLine($"\n# {content.Message.Role}{(isCode ? "\n# Generated Code:\n" : ":")}{content.Message.Content}");
|
||||
}
|
||||
|
||||
// Check for the citations
|
||||
foreach (var item in content.Message.Items)
|
||||
{
|
||||
// Process each item in the message
|
||||
if (item is AnnotationContent annotation)
|
||||
{
|
||||
if (annotation.Kind != AnnotationKind.UrlCitation)
|
||||
{
|
||||
Console.WriteLine($" [{item.GetType().Name}] {annotation.Label}: File #{annotation.ReferenceId}");
|
||||
}
|
||||
}
|
||||
else if (item is FileReferenceContent fileReference)
|
||||
{
|
||||
Console.WriteLine($" [{item.GetType().Name}] File #{fileReference.FileId}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
// Define the assistant
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(model, enableCodeInterpreter: true);
|
||||
|
||||
// Create the agent
|
||||
OpenAIAssistantAgent skAgent = new(assistant, assistantsClient);
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
Console.WriteLine(result);
|
||||
|
||||
// Extracts via breaking glass the code generated by code interpreter tool
|
||||
var chatResponse = result.RawRepresentation as ChatResponse;
|
||||
StringBuilder generatedCode = new();
|
||||
foreach (object? updateRawRepresentation in chatResponse?.RawRepresentation as IEnumerable<object?> ?? [])
|
||||
{
|
||||
if (updateRawRepresentation is RunStepDetailsUpdate update && update.CodeInterpreterInput is not null)
|
||||
{
|
||||
generatedCode.Append(update.CodeInterpreterInput);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(generatedCode.ToString()))
|
||||
{
|
||||
Console.WriteLine($"\n# {chatResponse?.Messages[0].Role}:Generated Code:\n{generatedCode}");
|
||||
}
|
||||
|
||||
// Check for the citations
|
||||
foreach (var textContent in result.Messages[0].Contents.OfType<Microsoft.Extensions.AI.TextContent>())
|
||||
{
|
||||
foreach (var annotation in textContent.Annotations ?? [])
|
||||
{
|
||||
if (annotation is CitationAnnotation citation)
|
||||
{
|
||||
if (citation.Url is null)
|
||||
{
|
||||
Console.WriteLine($" [{citation.GetType().Name}] {citation.Snippet}: File #{citation.FileId}");
|
||||
}
|
||||
|
||||
foreach (var region in citation.AnnotatedRegions ?? [])
|
||||
{
|
||||
if (region is TextSpanAnnotatedRegion textSpanRegion)
|
||||
{
|
||||
Console.WriteLine($"\n[TextSpan Region] {textSpanRegion.StartIndex}-{textSpanRegion.EndIndex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantsClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = await assistantsClient.CreateAIAgentAsync(model, tools: [new HostedCodeInterpreterTool()]);
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
Console.WriteLine(result);
|
||||
|
||||
// Extracts via breaking glass the code generated by code interpreter tool
|
||||
var chatResponse = result.RawRepresentation as ChatResponse;
|
||||
StringBuilder generatedCode = new();
|
||||
foreach (object? updateRawRepresentation in chatResponse?.RawRepresentation as IEnumerable<object?> ?? [])
|
||||
{
|
||||
if (updateRawRepresentation is RunStepDetailsUpdate update && update.CodeInterpreterInput is not null)
|
||||
{
|
||||
generatedCode.Append(update.CodeInterpreterInput);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(generatedCode.ToString()))
|
||||
{
|
||||
Console.WriteLine($"\n# {chatResponse?.Messages[0].Role}:Generated Code:\n{generatedCode}");
|
||||
}
|
||||
|
||||
// Check for the citations
|
||||
foreach (var textContent in result.Messages[0].Contents.OfType<Microsoft.Extensions.AI.TextContent>())
|
||||
{
|
||||
foreach (var annotation in textContent.Annotations ?? [])
|
||||
{
|
||||
if (annotation is CitationAnnotation citation)
|
||||
{
|
||||
if (citation.Url is null)
|
||||
{
|
||||
Console.WriteLine($" [{citation.GetType().Name}] {citation.Snippet}: File #{citation.FileId}");
|
||||
}
|
||||
|
||||
foreach (var region in citation.AnnotatedRegions ?? [])
|
||||
{
|
||||
if (region is TextSpanAnnotatedRegion textSpanRegion)
|
||||
{
|
||||
Console.WriteLine($"\n[TextSpan Region] {textSpanRegion.StartIndex}-{textSpanRegion.EndIndex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantsClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
@@ -63,7 +64,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
@@ -80,17 +81,17 @@ async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new OpenAIClient(apiKey).GetResponsesClient().AsIChatClient(model)
|
||||
.CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes.");
|
||||
var agent = new OpenAIClient(apiKey).GetResponsesClient()
|
||||
.AsAIAgent(model: model, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
+7
-6
@@ -6,6 +6,7 @@ using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
using OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
@@ -131,7 +132,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new()
|
||||
{
|
||||
MaxOutputTokens = 8000,
|
||||
@@ -176,10 +177,10 @@ async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new OpenAIClient(apiKey).GetResponsesClient().AsIChatClient(model)
|
||||
.CreateAIAgent(name: "Thinker", instructions: "You are at thinking hard before answering.");
|
||||
var agent = new OpenAIClient(apiKey).GetResponsesClient()
|
||||
.AsAIAgent(model: model, name: "Thinker", instructions: "You are at thinking hard before answering.");
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new()
|
||||
{
|
||||
MaxOutputTokens = 8000,
|
||||
@@ -190,7 +191,7 @@ async Task AFAgentAsync()
|
||||
}
|
||||
});
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
|
||||
// Retrieve the thinking as a full text block requires flattening multiple TextReasoningContents from multiple messages content lists.
|
||||
string assistantThinking = string.Join("\n", result.Messages
|
||||
@@ -203,7 +204,7 @@ async Task AFAgentAsync()
|
||||
Console.WriteLine($"Assistant: \n{assistantText}\n---\n");
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
var thinkingContents = update.Contents
|
||||
.OfType<TextReasoningContent>()
|
||||
|
||||
@@ -5,6 +5,7 @@ using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
@@ -63,7 +64,8 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
var agent = new OpenAIClient(apiKey).GetResponsesClient().AsIChatClient(model).CreateAIAgent(
|
||||
var agent = new OpenAIClient(apiKey).GetResponsesClient().AsAIAgent(
|
||||
model: model,
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
|
||||
+3
-2
@@ -5,6 +5,7 @@ using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
@@ -65,8 +66,8 @@ async Task AFAgentAsync()
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient((sp) => new OpenAIClient(apiKey)
|
||||
.GetResponsesClient().AsIChatClient(model)
|
||||
.CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes."));
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(model: model, name: "Joker", instructions: "You are good at telling jokes."));
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using CommunityToolkit.VectorData.InMemory;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Connectors.InMemory;
|
||||
using Microsoft.SemanticKernel.Functions;
|
||||
|
||||
namespace Agents;
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using CommunityToolkit.VectorData.InMemory;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Connectors.InMemory;
|
||||
using Microsoft.SemanticKernel.Data;
|
||||
|
||||
namespace Agents;
|
||||
|
||||
@@ -19,7 +19,7 @@ Prefix|Description
|
||||
---|---
|
||||
OpenAIAssistant|How to use agents based on the [Open AI Assistant API](https://platform.openai.com/docs/assistants).
|
||||
MixedChat|How to combine different agent types.
|
||||
ComplexChat|How to deveop complex agent chat solutions.
|
||||
ComplexChat|How to develop complex agent chat solutions.
|
||||
Legacy|How to use the legacy _Experimental Agent API_.
|
||||
|
||||
## Legacy Agents
|
||||
|
||||
@@ -77,18 +77,18 @@ public class SemanticCachingWithFilters(ITestOutputHelper output) : BaseTest(out
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executing similar requests two times using Azure Cosmos DB for MongoDB caching store to compare execution time and results.
|
||||
/// Executing similar requests two times using Azure DocumentDB caching store to compare execution time and results.
|
||||
/// Second execution is faster, because the result is returned from cache.
|
||||
/// How to setup Azure Cosmos DB for MongoDB cluster: https://learn.microsoft.com/en-gb/azure/cosmos-db/mongodb/vcore/quickstart-portal
|
||||
/// How to set up Azure DocumentDB: https://learn.microsoft.com/azure/documentdb/quickstart-portal
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task CosmosMongoDBCacheAsync()
|
||||
public async Task DocumentDbCacheAsync()
|
||||
{
|
||||
var kernel = GetKernelWithCache(services =>
|
||||
{
|
||||
services.AddCosmosMongoVectorStore(
|
||||
TestConfiguration.CosmosMongo.ConnectionString,
|
||||
TestConfiguration.CosmosMongo.DatabaseName);
|
||||
services.AddDocumentDBVectorStore(
|
||||
TestConfiguration.AzureDocumentDb.ConnectionString,
|
||||
TestConfiguration.AzureDocumentDb.DatabaseName);
|
||||
});
|
||||
|
||||
var result1 = await ExecuteAsync(kernel, "First run", "What's the tallest building in New York?");
|
||||
@@ -293,7 +293,7 @@ public class SemanticCachingWithFilters(ITestOutputHelper output) : BaseTest(out
|
||||
[VectorStoreData]
|
||||
public string Result { get; set; }
|
||||
|
||||
[VectorStoreVector(Dimensions: 1536)]
|
||||
[VectorStoreVector(1536)]
|
||||
public ReadOnlyMemory<float> PromptEmbedding { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
|
||||
namespace ChatCompletion;
|
||||
|
||||
#pragma warning disable SKEXP0010 // OpenAIPromptExecutionSettings.ExtraBody is experimental.
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="OpenAIPromptExecutionSettings.ExtraBody"/> is an escape hatch that injects additional fields
|
||||
/// into the request body sent to the OpenAI-compatible endpoint. Use it to pass vendor-specific or preview
|
||||
/// parameters that are not modeled by <see cref="OpenAIPromptExecutionSettings"/> (for example,
|
||||
/// Qwen3's <c>enable_thinking</c> flag, ChatGLM thinking modes, or NVIDIA NIM custom knobs).
|
||||
///
|
||||
/// <para>Key syntax:</para>
|
||||
/// <list type="bullet">
|
||||
/// <item><description>A plain key (without leading <c>$.</c>) is treated as a literal top-level field name.</description></item>
|
||||
/// <item><description>A key starting with <c>$.</c> is interpreted as a JSONPath expression and applied as a deep patch onto the request body.</description></item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public class OpenAI_ChatCompletionExtraBody(ITestOutputHelper output) : BaseTest(output)
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds a flat top-level field to the outgoing chat completion request:
|
||||
/// <code>{ "messages": [...], "model": "qwen-plus", "enable_thinking": false, ... }</code>
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task FlatFieldExampleAsync()
|
||||
{
|
||||
OpenAIChatCompletionService chatCompletionService = new(
|
||||
TestConfiguration.OpenAI.ChatModelId,
|
||||
TestConfiguration.OpenAI.ApiKey);
|
||||
|
||||
var settings = new OpenAIPromptExecutionSettings
|
||||
{
|
||||
ExtraBody = new Dictionary<string, object?>
|
||||
{
|
||||
// Required by Qwen3 open-source models for non-streaming calls.
|
||||
["enable_thinking"] = false,
|
||||
},
|
||||
};
|
||||
|
||||
var chatHistory = new ChatHistory("You are a helpful assistant.");
|
||||
chatHistory.AddUserMessage("Who are you?");
|
||||
|
||||
var reply = await chatCompletionService.GetChatMessageContentAsync(chatHistory, settings);
|
||||
|
||||
Console.WriteLine(reply.Content);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses a <c>$.</c>-prefixed JSONPath key to surgically patch a nested field in the request body
|
||||
/// (for example, into <c>thinking.enabled</c>). This avoids having to specify the entire nested object.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task DeepPatchExampleAsync()
|
||||
{
|
||||
OpenAIChatCompletionService chatCompletionService = new(
|
||||
TestConfiguration.OpenAI.ChatModelId,
|
||||
TestConfiguration.OpenAI.ApiKey);
|
||||
|
||||
var settings = new OpenAIPromptExecutionSettings
|
||||
{
|
||||
ExtraBody = new Dictionary<string, object?>
|
||||
{
|
||||
// Emits { "thinking": { "enabled": false } } in the request body.
|
||||
["$.thinking.enabled"] = false,
|
||||
},
|
||||
};
|
||||
|
||||
var chatHistory = new ChatHistory("You are a helpful assistant.");
|
||||
chatHistory.AddUserMessage("Summarize the plot of Hamlet in one sentence.");
|
||||
|
||||
var reply = await chatCompletionService.GetChatMessageContentAsync(chatHistory, settings);
|
||||
|
||||
Console.WriteLine(reply.Content);
|
||||
}
|
||||
}
|
||||
@@ -12,8 +12,7 @@ namespace ChatCompletion;
|
||||
/// <remarks>
|
||||
/// Currently, web search is only supported with the following models:
|
||||
/// <list type="bullet">
|
||||
/// <item>gpt-4o-search-preview</item>
|
||||
/// <item>gpt-4o-mini-search-preview</item>
|
||||
/// <item>gpt-5-search-ap</item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
public class OpenAI_ChatCompletioWebSearch(ITestOutputHelper output) : BaseTest(output)
|
||||
@@ -24,7 +23,7 @@ public class OpenAI_ChatCompletioWebSearch(ITestOutputHelper output) : BaseTest(
|
||||
Assert.NotNull(TestConfiguration.OpenAI.ApiKey);
|
||||
|
||||
// Ensure you use a supported model
|
||||
var modelId = "gpt-4o-mini-search-preview";
|
||||
var modelId = "gpt-5-search-api";
|
||||
var settings = new OpenAIPromptExecutionSettings
|
||||
{
|
||||
WebSearchOptions = new ChatWebSearchOptions()
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<!-- Suppress: "Declare types in namespaces", "Require ConfigureAwait", "Experimental" -->
|
||||
<NoWarn>$(NoWarn);CS8618,IDE0009,IDE1006,CA1051,CA1050,CA1707,CA1054,CA2007,VSTHRD111,CS1591,RCS1110,RCS1243,CA5394,SKEXP0001,SKEXP0010,SKEXP0020,SKEXP0040,SKEXP0050,SKEXP0060,SKEXP0101,SKEXP0110,OPENAI001,CA1724,IDE1006,IDE0009,MEVD9000</NoWarn>
|
||||
<!-- CommunityToolkit.VectorData.AzureCosmosDB pulls Microsoft.Azure.Cosmos which added a mandatory Newtonsoft.Json explicit-reference check; disable it since we don't use Newtonsoft.Json directly -->
|
||||
<AzureCosmosDisableNewtonsoftJsonCheck>true</AzureCosmosDisableNewtonsoftJsonCheck>
|
||||
<OutputType>Library</OutputType>
|
||||
<UserSecretsId>5ee045b0-aea3-4f08-8d31-32d1a6f8fed0</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
@@ -49,6 +51,12 @@
|
||||
<PackageReference Include="AWSSDK.Core" />
|
||||
<PackageReference Include="AWSSDK.SecurityToken" />
|
||||
<PackageReference Include="Grpc.Net.ClientFactory" />
|
||||
<PackageReference Include="CommunityToolkit.VectorData.AzureAISearch" />
|
||||
<PackageReference Include="CommunityToolkit.VectorData.AzureDocumentDB" />
|
||||
<PackageReference Include="CommunityToolkit.VectorData.InMemory" />
|
||||
<PackageReference Include="CommunityToolkit.VectorData.Qdrant" />
|
||||
<PackageReference Include="CommunityToolkit.VectorData.PgVector" />
|
||||
<PackageReference Include="CommunityToolkit.VectorData.Redis" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
@@ -71,17 +79,6 @@
|
||||
<ProjectReference Include="..\..\src\Connectors\Connectors.Onnx\Connectors.Onnx.csproj" />
|
||||
<ProjectReference Include="..\..\src\Connectors\Connectors.Ollama\Connectors.Ollama.csproj" />
|
||||
<ProjectReference Include="..\..\src\Connectors\Connectors.OpenAI\Connectors.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\src\VectorData\AzureAISearch\AzureAISearch.csproj" />
|
||||
<ProjectReference Include="..\..\src\VectorData\CosmosMongoDB\CosmosMongoDB.csproj" />
|
||||
<ProjectReference Include="..\..\src\VectorData\Chroma\Chroma.csproj" />
|
||||
<ProjectReference Include="..\..\src\VectorData\InMemory\InMemory.csproj" />
|
||||
<ProjectReference Include="..\..\src\VectorData\MongoDB\MongoDB.csproj" />
|
||||
<ProjectReference Include="..\..\src\VectorData\Pinecone\Pinecone.csproj" />
|
||||
<ProjectReference Include="..\..\src\VectorData\PgVector\PgVector.csproj" />
|
||||
<ProjectReference Include="..\..\src\VectorData\Qdrant\Qdrant.csproj" />
|
||||
<ProjectReference Include="..\..\src\VectorData\Redis\Redis.csproj" />
|
||||
<ProjectReference Include="..\..\src\VectorData\SqliteVec\SqliteVec.csproj" />
|
||||
<ProjectReference Include="..\..\src\VectorData\Weaviate\Weaviate.csproj" />
|
||||
<ProjectReference Include="..\..\src\Experimental\Orchestration.Flow\Experimental.Orchestration.Flow.csproj" />
|
||||
<ProjectReference Include="..\..\src\Extensions\PromptTemplates.Handlebars\PromptTemplates.Handlebars.csproj" />
|
||||
<ProjectReference Include="..\..\src\Extensions\PromptTemplates.Liquid\PromptTemplates.Liquid.csproj" />
|
||||
|
||||
@@ -253,7 +253,7 @@ public class LocalExamplePlugin(ITestOutputHelper output)
|
||||
[KernelFunction]
|
||||
public async Task<string> TaskInjectingCancellationTokenWithStringResult(CancellationToken cancellationToken)
|
||||
{
|
||||
var result = $"Cancellation resquested: {cancellationToken.IsCancellationRequested}";
|
||||
var result = $"Cancellation requested: {cancellationToken.IsCancellationRequested}";
|
||||
this._output.WriteLine($"Running {nameof(this.TaskInjectingCultureInfoOrIFormatProviderWithStringResult)} -> Injected Cancellation Token -> result: {result}");
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Text.Json;
|
||||
using CommunityToolkit.VectorData.InMemory;
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using Microsoft.SemanticKernel.Connectors.HuggingFace;
|
||||
using Microsoft.SemanticKernel.Connectors.SqliteVec;
|
||||
using Microsoft.SemanticKernel.Embeddings;
|
||||
|
||||
#pragma warning disable CS8602 // Dereference of a possibly null reference.
|
||||
@@ -32,12 +32,11 @@ public class HuggingFace_TextEmbeddingCustomHttpHandler(ITestOutputHelper output
|
||||
})
|
||||
);
|
||||
|
||||
var sqliteCollection = new SqliteCollection<string, Record>(
|
||||
"Data Source=./../../../Sqlite.sqlite",
|
||||
var inMemoryCollection = new InMemoryCollection<string, Record>(
|
||||
name: "Test",
|
||||
new() { EmbeddingGenerator = hf.AsEmbeddingGenerator() });
|
||||
|
||||
await sqliteCollection.UpsertAsync(new Record
|
||||
await inMemoryCollection.UpsertAsync(new Record
|
||||
{
|
||||
Id = "1",
|
||||
Text = "THIS IS A SAMPLE",
|
||||
@@ -53,7 +52,7 @@ public class HuggingFace_TextEmbeddingCustomHttpHandler(ITestOutputHelper output
|
||||
[VectorStoreData]
|
||||
public string Text { get; set; }
|
||||
|
||||
[VectorStoreVector(Dimensions: 768)]
|
||||
[VectorStoreVector(768)]
|
||||
public string Embedding { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ Jane: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, nunc
|
||||
Jane: Darn, it's just repeating stuff now.
|
||||
John: I think we're done.
|
||||
Jane: We're not though! We need like 1500 more characters.
|
||||
John: Oh Cananda, our home and native land.
|
||||
John: Oh Canada, our home and native land.
|
||||
Jane: True patriot love in all thy sons command.
|
||||
John: With glowing hearts we see thee rise.
|
||||
Jane: The True North strong and free.
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using Microsoft.SemanticKernel.Connectors.Pinecone;
|
||||
using Pinecone;
|
||||
|
||||
namespace Memory.VectorStoreLangchainInterop;
|
||||
|
||||
/// <summary>
|
||||
/// Contains a factory method that can be used to create a Pinecone vector store that is compatible with datasets ingested using Langchain.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class is used with the <see cref="VectorStore_Langchain_Interop"/> sample.
|
||||
/// </remarks>
|
||||
public static class PineconeFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Record definition that matches the storage format used by Langchain for Pinecone.
|
||||
/// </summary>
|
||||
private static readonly VectorStoreCollectionDefinition s_definition = new()
|
||||
{
|
||||
Properties =
|
||||
[
|
||||
new VectorStoreKeyProperty("Key", typeof(string)),
|
||||
new VectorStoreDataProperty("Content", typeof(string)) { StorageName = "text" },
|
||||
new VectorStoreDataProperty("Source", typeof(string)) { StorageName = "source" },
|
||||
new VectorStoreVectorProperty("Embedding", typeof(ReadOnlyMemory<float>), 1536) { StorageName = "embedding" }
|
||||
]
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Create a new Pinecone-backed <see cref="VectorStore"/> that can be used to read data that was ingested using Langchain.
|
||||
/// </summary>
|
||||
/// <param name="pineconeClient">Pinecone client that can be used to manage the collections and points in a Pinecone store.</param>
|
||||
/// <returns>The <see cref="VectorStore"/>.</returns>
|
||||
public static VectorStore CreatePineconeLangchainInteropVectorStore(PineconeClient pineconeClient)
|
||||
=> new PineconeLangchainInteropVectorStore(new PineconeVectorStore(pineconeClient), pineconeClient);
|
||||
|
||||
private sealed class PineconeLangchainInteropVectorStore(
|
||||
VectorStore innerStore,
|
||||
PineconeClient pineconeClient)
|
||||
: VectorStore
|
||||
{
|
||||
private readonly PineconeClient _pineconeClient = pineconeClient;
|
||||
|
||||
public override VectorStoreCollection<TKey, TRecord> GetCollection<TKey, TRecord>(string name, VectorStoreCollectionDefinition? definition = null)
|
||||
{
|
||||
if (typeof(TKey) != typeof(string) || typeof(TRecord) != typeof(LangchainDocument<string>))
|
||||
{
|
||||
throw new NotSupportedException("This VectorStore is only usable with string keys and LangchainDocument<string> record types");
|
||||
}
|
||||
|
||||
// Create a Pinecone collection and pass in our custom record definition that matches
|
||||
// the schema used by Langchain so that the default mapper can use the storage names
|
||||
// in it, to map to the storage scheme.
|
||||
return (new PineconeCollection<TKey, TRecord>(
|
||||
_pineconeClient,
|
||||
name,
|
||||
new()
|
||||
{
|
||||
Definition = s_definition
|
||||
}) as VectorStoreCollection<TKey, TRecord>)!;
|
||||
}
|
||||
|
||||
public override VectorStoreCollection<object, Dictionary<string, object?>> GetDynamicCollection(string name, VectorStoreCollectionDefinition? definition = null)
|
||||
{
|
||||
// Create a Pinecone collection and pass in our custom record definition that matches
|
||||
// the schema used by Langchain so that the default mapper can use the storage names
|
||||
// in it, to map to the storage scheme.
|
||||
return new PineconeDynamicCollection(
|
||||
_pineconeClient,
|
||||
name,
|
||||
new()
|
||||
{
|
||||
Definition = s_definition
|
||||
});
|
||||
}
|
||||
|
||||
public override object? GetService(Type serviceType, object? serviceKey = null) => innerStore.GetService(serviceType, serviceKey);
|
||||
|
||||
public override IAsyncEnumerable<string> ListCollectionNamesAsync(CancellationToken cancellationToken = default) => innerStore.ListCollectionNamesAsync(cancellationToken);
|
||||
|
||||
public override Task<bool> CollectionExistsAsync(string name, CancellationToken cancellationToken = default) => innerStore.CollectionExistsAsync(name, cancellationToken);
|
||||
|
||||
public override Task EnsureCollectionDeletedAsync(string name, CancellationToken cancellationToken = default) => innerStore.EnsureCollectionDeletedAsync(name, cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using CommunityToolkit.VectorData.Redis;
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using Microsoft.SemanticKernel.Connectors.Redis;
|
||||
using StackExchange.Redis;
|
||||
|
||||
namespace Memory.VectorStoreLangchainInterop;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user