在C#程序中调用大模型的API接口

当前,以ChatGPT、DeepSeek为代表的各种大语言模型层出不穷,让我们切实感受到人工智能的强大。如果能在程序中集成大语言模型的问答能力,那么将能实现一些非常有用和非常有趣的需求。

本文简单介绍在C#应用中调用大模型接口的几种方法,其中基于HttpClient的原生方法、OpenAPI包是两种通用方法,前者依赖最少推荐。

以下示例借助DeepSeek实现语言翻译功能。

基于HttpClient的原生方法

以下是访问自部署的大模型接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
private async Task OKAsync() {
var apiKey = "sk-XXX";
var apiUrl = "http://XXX.XXX.XXX.XXX:XXX/v1/chat/completions";

if (string.IsNullOrWhiteSpace(Input)) return;

var requestContent = new {
model = "crcc-qwen3",
messages = new[]
{
new { role = "system", content = "你是一个语言翻译家,擅长将中文翻译成英文!请只输出翻译后的文本,不要输出其他不相关的文字。" },
new { role = "user", content = $"请翻译'{Input}'为英语!" }
},
Stream = false,
};

var json = JsonSerializer.Serialize(requestContent, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
var httpContent = new StringContent(json, Encoding.UTF8, "application/json");

using var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Clear();
httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");

try {
var response = await httpClient.PostAsync(apiUrl, httpContent);
response.EnsureSuccessStatusCode();

var responseBody = await response.Content.ReadAsStringAsync();
using var jsonDocument = JsonDocument.Parse(responseBody);
var root = jsonDocument.RootElement;

if (root.TryGetProperty("choices", out var choices) && choices.GetArrayLength() > 0) {
var content = choices[0].GetProperty("message").GetProperty("content").GetString();
Output = content;
} else {
Output = "No result returned.";
}
} catch (HttpRequestException ex) {
Output = $"HTTP Error: {ex.Message}";
} catch (Exception ex) {
Output = $"Error: {ex.Message}";
}
}

如果是访问DeepSeek的官方接口:

1
2
3
4
5
6
7
8
9
10
11
12
var apiKey = "sk-XXX";
var apiUrl = "https://api.deepseek.com/v1/chat/completions";
var requestContent = new {
model = "deepseek-chat",
messages = new[]
{
new { role = "system", content = "你是一个语言翻译家,擅长将中文翻译成英文!请只输出翻译后的文本,不要输出其他不相关的文字。" },
new { role = "user", content = $"请翻译'{Input}'为英语!" }
},
// 不使用流模式,即整体输出最终结果
Stream = false,
};

使用OpenAPI包访问

安装以下NuGet包:

使用方法如下,非常简洁,以下是访问自部署的大模型接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
static async Task Main() {
var client = new ChatClient(
"crcc-qwen3",
new ApiKeyCredential("sk-XXX"),
new OpenAIClientOptions() {
Endpoint = new Uri("http://XXX.XXX.XXX.XXX:54000/v1")
}
);
var res =await client.CompleteChatAsync(
ChatMessage.CreateSystemMessage("你是一个语言翻译家,擅长将中文翻译成英文!请只输出翻译后的文本,不要输出其他不相关的文字。"),
ChatMessage.CreateUserMessage($"请翻译'这是一个挑战!'为英语!"),
);
Console.WriteLine( res.Value.Content.FirstOrDefault().Text );
}

如果是访问DeepSeek的官方接口:

1
2
3
4
5
6
7
8
9
10
static async Task Main() {
var client = new ChatClient(
"deepseek-chat",
new ApiKeyCredential("sk-XXX"),
new OpenAIClientOptions() {
Endpoint = new Uri("https://api.deepseek.com/v1")
}
);
// ......
}

但是最终程序会依赖很多类库,较为冗余:

DeepSeek.Core库

该库仅支持访问官方DeepSeek大模型接口,只需要传递APIKey和消息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private async Task OKAsync() {
if (string.IsNullOrWhiteSpace(Input)) return;

var apiKey = "sk-XXX";
var client = new DeepSeekClient(apiKey);
var request = new ChatRequest {
Messages = [
Message.NewSystemMessage("你是一个语言翻译家,擅长将中文翻译成英文!请只输出翻译后的文本,不要输出其他不相关的文字。"),
Message.NewUserMessage($"请翻译'{Input}'为英语!")
],
Model = DeepSeekModels.ChatModel
};

var chatResponse = await client.ChatAsync(request, CancellationToken.None);
Output = chatResponse?.Choices.First().Message?.Content;
}

访问Ollama上部署的大模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
using System.Text;
using System.Text.Json;

namespace OllamaClient {
public class OllamaRequest {
public string Model { get; set; } = string.Empty;
public string Prompt { get; set; } = string.Empty;
public bool Stream { get; set; } = false;
}

public class OllamaResponse {
public string Model { get; set; } = string.Empty;
public string Response { get; set; } = string.Empty;
public bool Done { get; set; }
}

internal class Program {
private static readonly HttpClient client = new HttpClient();
private const string OllamaApiUrl = "http://XXX.XXX.XXX.XXX:XXX/api/generate";

static async Task Main(string[] args) {
var request = new OllamaRequest {
Model = "gpt-oss:20b",
Prompt = "你是一个语言翻译家,擅长将中文翻译成英文!请只输出翻译后的文本,不要输出其他不相关的文字。请翻译`翻译家`这句话。",
Stream = false,
};

try {
var response = await CallOllamaAsync(request);
Console.WriteLine("\n模型回复:\n");
Console.WriteLine(response.Response);
} catch (Exception ex) {
Console.WriteLine($"调用失败: {ex.Message}");
}

Console.WriteLine("\n按任意键退出...");
Console.ReadKey();
}

static async Task<OllamaResponse> CallOllamaAsync(OllamaRequest request) {
var options = new JsonSerializerOptions {
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};
var json = JsonSerializer.Serialize(request, options);
var content = new StringContent(json, Encoding.UTF8, "application/json");

var httpResponse = await client.PostAsync(OllamaApiUrl, content);
httpResponse.EnsureSuccessStatusCode();

var jsonResponse = await httpResponse.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<OllamaResponse>(jsonResponse, options);

if (result == null)
throw new Exception("反序列化失败");

return result;
}
}
}

效果

(转载本站文章请注明作者和出处lihaohello.top,请勿用于任何商业用途)

评论