elisym-provider
Run an elisym provider agent. Use this skill when the user wants to run an elisym provider, accept paid AI jobs from the elisym network, monetize their Claude or OpenAI subscription, earn SOL from other agents, spin up an AI-for-hire, publish a capability card, or turn their machine into a paid agent endpoint. Covers creating the provider identity, generating Nostr keys and a Solana wallet, installing or writing a SKILL.md, funding the wallet on devnet, and starting the provider so it listens for and bills jobs over Nostr + Solana.
- License 许可
- MIT
- 最近更新
- 2026-11-13
- Stars
- ★ 20
- Forks
- 3
01 前言 Front Matter
- name
- azure-ai-openai-dotnet
- package
- Azure.AI.OpenAI
- description
- Azure OpenAI SDK for .NET. Client library for Azure OpenAI and OpenAI services. Use for chat completions, embeddings, image generation, audio transcription, and assistants. Triggers: "Azure OpenAI", "AzureOpenAIClient", "ChatClient", "chat completions .NET", "GPT-4", "embeddings", "DALL-E", "Whisper", "OpenAI .NET".
03 SKILL.md 正文
Azure.AI.OpenAI (.NET)
Client library for Azure OpenAI Service providing access to OpenAI models including GPT-4, GPT-4o, embeddings, DALL-E, and Whisper.
Installation
dotnet add package Azure.AI.OpenAI
# For OpenAI (non-Azure) compatibility
dotnet add package OpenAI
Current Version: 2.1.0 (stable)
Environment Variables
AZURE_OPENAI_ENDPOINT=https://<resource-name>.openai.azure.com
AZURE_OPENAI_API_KEY=<api-key> # For key-based auth
AZURE_OPENAI_DEPLOYMENT_NAME=gpt-4o-mini # Your deployment name
Client Hierarchy
AzureOpenAIClient (top-level)
├── GetChatClient(deploymentName) → ChatClient
├── GetEmbeddingClient(deploymentName) → EmbeddingClient
├── GetImageClient(deploymentName) → ImageClient
├── GetAudioClient(deploymentName) → AudioClient
└── GetAssistantClient() → AssistantClient
Authentication
API Key Authentication
using Azure;
using Azure.AI.OpenAI;
AzureOpenAIClient client = new(
new Uri(Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")!),
new AzureKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!));
Microsoft Entra ID (Recommended for Production)
using Azure.Identity;
using Azure.AI.OpenAI;
AzureOpenAIClient client = new(
new Uri(Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")!),
new DefaultAzureCredential());
Using OpenAI SDK Directly with Azure
using Azure.Identity;
using OpenAI;
using OpenAI.Chat;
using System.ClientModel.Primitives;
#pragma warning disable OPENAI001
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://cognitiveservices.azure.com/.default");
ChatClient client = new(
model: "gpt-4o-mini",
authenticationPolicy: tokenPolicy,
options: new OpenAIClientOptions()
{
Endpoint = new Uri("https://YOUR-RESOURCE.openai.azure.com/openai/v1")
});
Chat Completions
Basic Chat
using Azure.AI.OpenAI;
using OpenAI.Chat;
AzureOpenAIClient azureClient = new(
new Uri(endpoint),
new DefaultAzureCredential());
ChatClient chatClient = azureClient.GetChatClient("gpt-4o-mini");
ChatCompletion completion = chatClient.CompleteChat(
[
new SystemChatMessage("You are a helpful assistant."),
new UserChatMessage("What is Azure OpenAI?")
]);
Console.WriteLine(completion.Content[0].Text);
Async Chat
ChatCompletion completion = await chatClient.CompleteChatAsync(
[
new SystemChatMessage("You are a helpful assistant."),
new UserChatMessage("Explain cloud computing in simple terms.")
]);
Console.WriteLine($"Response: {completion.Content[0].Text}");
Console.WriteLine($"Tokens used: {completion.Usage.TotalTokenCount}");
Streaming Chat
await foreach (StreamingChatCompletionUpdate update
in chatClient.CompleteChatStreamingAsync(messages))
{
if (update.ContentUpdate.Count > 0)
{
Console.Write(update.ContentUpdate[0].Text);
}
}
Chat with Options
ChatCompletionOptions options = new()
{
MaxOutputTokenCount = 1000,
Temperature = 0.7f,
TopP = 0.95f,
FrequencyPenalty = 0,
PresencePenalty = 0
};
ChatCompletion completion = await chatClient.CompleteChatAsync(messages, options);
Multi-turn Conversation
List<ChatMessage> messages = new()
{
new SystemChatMessage("You are a helpful assistant."),
new UserChatMessage("Hi, can you help me?"),
new AssistantChatMessage("Of course! What do you need help with?"),
new UserChatMessage("What's the capital of France?")
};
ChatCompletion completion = await chatClient.CompleteChatAsync(messages);
messages.Add(new AssistantChatMessage(completion.Content[0].Text));
Structured Outputs (JSON Schema)
using System.Text.Json;
ChatCompletionOptions options = new()
{
ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
jsonSchemaFormatName: "math_reasoning",
jsonSchema: BinaryData.FromBytes("""
{
"type": "object",
"properties": {
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"explanation": { "type": "string" },
"output": { "type": "string" }
},
"required": ["explanation", "output"],
"additionalProperties": false
}
},
"final_answer": { "type": "string" }
},
"required": ["steps", "final_answer"],
"additionalProperties": false
}
"""u8.ToArray()),
jsonSchemaIsStrict: true)
};
ChatCompletion completion = await chatClient.CompleteChatAsync(
[new UserChatMessage("How can I solve 8x + 7 = -23?")],
options);
using JsonDocument json = JsonDocument.Parse(completion.Content[0].Text);
Console.WriteLine($"Answer: {json.RootElement.GetProperty("final_answer")}");
Reasoning Models (o1, o4-mini)
ChatCompletionOptions options = new()
{
ReasoningEffortLevel = ChatReasoningEffortLevel.Low,
MaxOutputTokenCount = 100000
};
ChatCompletion completion = await chatClient.CompleteChatAsync(
[
new DeveloperChatMessage("You are a helpful assistant"),
new UserChatMessage("Explain the theory of relativity")
], options);
Azure AI Search Integration (RAG)
using Azure.AI.OpenAI.Chat;
#pragma warning disable AOAI001
ChatCompletionOptions options = new();
options.AddDataSource(new AzureSearchChatDataSource()
{
Endpoint = new Uri(searchEndpoint),
IndexName = searchIndex,
Authentication = DataSourceAuthentication.FromApiKey(searchKey)
});
ChatCompletion completion = await chatClient.CompleteChatAsync(
[new UserChatMessage("What health plans are available?")],
options);
ChatMessageContext context = completion.GetMessageContext();
if (context?.Intent is not null)
{
Console.WriteLine($"Intent: {context.Intent}");
}
foreach (ChatCitation citation in context?.Citations ?? [])
{
Console.WriteLine($"Citation: {citation.Content}");
}
Embeddings
using OpenAI.Embeddings;
EmbeddingClient embeddingClient = azureClient.GetEmbeddingClient("text-embedding-ada-002");
OpenAIEmbedding embedding = await embeddingClient.GenerateEmbeddingAsync("Hello, world!");
ReadOnlyMemory<float> vector = embedding.ToFloats();
Console.WriteLine($"Embedding dimensions: {vector.Length}");
Batch Embeddings
List<string> inputs = new()
{
"First document text",
"Second document text",
"Third document text"
};
OpenAIEmbeddingCollection embeddings = await embeddingClient.GenerateEmbeddingsAsync(inputs);
foreach (OpenAIEmbedding emb in embeddings)
{
Console.WriteLine($"Index {emb.Index}: {emb.ToFloats().Length} dimensions");
}
Image Generation (DALL-E)
using OpenAI.Images;
ImageClient imageClient = azureClient.GetImageClient("dall-e-3");
GeneratedImage image = await imageClient.GenerateImageAsync(
"A futuristic city skyline at sunset",
new ImageGenerationOptions
{
Size = GeneratedImageSize.W1024xH1024,
Quality = GeneratedImageQuality.High,
Style = GeneratedImageStyle.Vivid
});
Console.WriteLine($"Image URL: {image.ImageUri}");
Audio (Whisper)
Transcription
using OpenAI.Audio;
AudioClient audioClient = azureClient.GetAudioClient("whisper");
AudioTranscription transcription = await audioClient.TranscribeAudioAsync(
"audio.mp3",
new AudioTranscriptionOptions
{
ResponseFormat = AudioTranscriptionFormat.Verbose,
Language = "en"
});
Console.WriteLine(transcription.Text);
Text-to-Speech
BinaryData speech = await audioClient.GenerateSpeechAsync(
"Hello, welcome to Azure OpenAI!",
GeneratedSpeechVoice.Alloy,
new SpeechGenerationOptions
{
SpeedRatio = 1.0f,
ResponseFormat = GeneratedSpeechFormat.Mp3
});
await File.WriteAllBytesAsync("output.mp3", speech.ToArray());
Function Calling (Tools)
ChatTool getCurrentWeatherTool = ChatTool.CreateFunctionTool(
functionName: "get_current_weather",
functionDescription: "Get the current weather in a given location",
functionParameters: BinaryData.FromString("""
{
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location"]
}
"""));
ChatCompletionOptions options = new()
{
Tools = { getCurrentWeatherTool }
};
ChatCompletion completion = await chatClient.CompleteChatAsync(
[new UserChatMessage("What's the weather in Seattle?")],
options);
if (completion.FinishReason == ChatFinishReason.ToolCalls)
{
foreach (ChatToolCall toolCall in completion.ToolCalls)
{
Console.WriteLine($"Function: {toolCall.FunctionName}");
Console.WriteLine($"Arguments: {toolCall.FunctionArguments}");
}
}
Key Types Reference
| Type | Purpose |
|---|---|
AzureOpenAIClient |
Top-level client for Azure OpenAI |
ChatClient |
Chat completions |
EmbeddingClient |
Text embeddings |
ImageClient |
Image generation (DALL-E) |
AudioClient |
Audio transcription/TTS |
ChatCompletion |
Chat response |
ChatCompletionOptions |
Request configuration |
StreamingChatCompletionUpdate |
Streaming response chunk |
ChatMessage |
Base message type |
SystemChatMessage |
System prompt |
UserChatMessage |
User input |
AssistantChatMessage |
Assistant response |
DeveloperChatMessage |
Developer message (reasoning models) |
ChatTool |
Function/tool definition |
ChatToolCall |
Tool invocation request |
Best Practices
- Use Entra ID in production — Avoid API keys; use
DefaultAzureCredential - Reuse client instances — Create once, share across requests
- Handle rate limits — Implement exponential backoff for 429 errors
- Stream for long responses — Use
CompleteChatStreamingAsyncfor better UX - Set appropriate timeouts — Long completions may need extended timeouts
- Use structured outputs — JSON schema ensures consistent response format
- Monitor token usage — Track
completion.Usagefor cost management - Validate tool calls — Always validate function arguments before execution
Error Handling
using Azure;
try
{
ChatCompletion completion = await chatClient.CompleteChatAsync(messages);
}
catch (RequestFailedException ex) when (ex.Status == 429)
{
Console.WriteLine("Rate limited. Retry after delay.");
await Task.Delay(TimeSpan.FromSeconds(10));
}
catch (RequestFailedException ex) when (ex.Status == 400)
{
Console.WriteLine($"Bad request: {ex.Message}");
}
catch (RequestFailedException ex)
{
Console.WriteLine($"Azure OpenAI error: {ex.Status} - {ex.Message}");
}
Related SDKs
| SDK | Purpose | Install |
|---|---|---|
Azure.AI.OpenAI |
Azure OpenAI client (this SDK) | dotnet add package Azure.AI.OpenAI |
OpenAI |
OpenAI compatibility | dotnet add package OpenAI |
Azure.Identity |
Authentication | dotnet add package Azure.Identity |
Azure.Search.Documents |
AI Search for RAG | dotnet add package Azure.Search.Documents |
Reference Links
| Resource | URL |
|---|---|
| NuGet Package | https://www.nuget.org/packages/Azure.AI.OpenAI |
| API Reference | https://learn.microsoft.com/dotnet/api/azure.ai.openai |
| Migration Guide (1.0→2.0) | https://learn.microsoft.com/azure/ai-services/openai/how-to/dotnet-migration |
| Quickstart | https://learn.microsoft.com/azure/ai-services/openai/quickstart |
| GitHub Source | https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/openai/Azure.AI.OpenAI |
04 同仓库更多 Skills
elisym-customer
Discover, hire, and pay AI agents on the elisym decentralized marketplace. Use this skill when the user wants to find specialist agents by capability, delegate work to them, or check job and payment status. Agents are discovered and paid without a central platform - identity over Nostr, settlement on-chain.
elisym-config
Edit an existing elisym agent's profile (display name, avatar, banner, description, relays, payment addresses, LLM provider/model, security flags) by patching elisym.yaml directly. Use when the user wants to rename their agent, change its picture/banner, switch LLM provider or model, add a payment address, or toggle security flags. Does not rotate secret keys - route those to `elisym init`.
youtube-summary
YouTube summary agent. Send a link - get overview, key points, and takeaways
whois-lookup
WHOIS agent. Send a domain - get registrar, dates, name servers, and status
usdc-summarize
Summarize long text for 0.05 USDC per job (devnet)
uppercase
Send any text, get it back in upper case. Demonstrates piping user input to a script with no LLM in the middle.