?.NET?MAUI如何開發(fā)AI平臺ChatGPT的客戶端?
Admin 2023-09-15 群英技術(shù)資訊 1723 次瀏覽
這篇文章給大家分享的是?.NET?MAUI如何開發(fā)AI平臺ChatGPT的客戶端?。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,文中的介紹得很詳細(xì),而要易于理解和學(xué)習(xí),有需要的朋友可以參考,接下來就跟隨小編一起了解看看吧。最近 chatgpt 很火,由于網(wǎng)頁版本限制了 ip,還得必須開代理,用起來比較麻煩,所以我嘗試用 maui 開發(fā)一個(gè)聊天小應(yīng)用,結(jié)合 chatgpt 的開放 api 來實(shí)現(xiàn)(很多客戶端使用網(wǎng)頁版本接口用 cookie 的方式,有很多限制(如下圖)總歸不是很正規(guī))。

效果如下

mac 端由于需要升級 macos13 才能開發(fā)調(diào)試,這部分我還沒有完成,不過 maui 的控件是跨平臺的,放在后續(xù)我升級系統(tǒng)再說。
我是設(shè)想開發(fā)一個(gè)類似 jetbrains 的 ToolBox 應(yīng)用一樣,啟動(dòng)程序在桌面右下角出現(xiàn)托盤圖標(biāo),點(diǎn)擊圖標(biāo)彈出應(yīng)用(風(fēng)格在 windows mac 平臺保持一致)
需要實(shí)現(xiàn)的功能一覽
新建一個(gè) maui 工程(vs2022)

坑一:默認(rèn)編譯出來的 exe 是直接雙擊打不開的

工程文件加上這個(gè)配置
<WindowsPackageType>None</WindowsPackageType> <WindowsAppSDKSelfContained Condition="'$(IsUnpackaged)' == 'true'">true</WindowsAppSDKSelfContained> <SelfContained Condition="'$(IsUnpackaged)' == 'true'">true</SelfContained>
以上修改后,編譯出來的 exe 雙擊就可以打開了
啟動(dòng)時(shí)設(shè)置窗口不能改變大小,隱藏 titlebar, 讓 Webview 控件占滿整個(gè)窗口

這里要根據(jù)平臺不同實(shí)現(xiàn)不同了,windows 平臺采用 winAPI 調(diào)用,具體看工程代碼吧!
在 MainPage.xaml 添加控件

對應(yīng)的靜態(tài) html 等文件放在工程的 Resource\Raw 文件夾下 (整個(gè)文件夾里面默認(rèn)是作為內(nèi)嵌資源打包的,工程文件里面的如下配置起的作用)
<!-- Raw Assets (also remove the "Resources\Raw" prefix) --> <MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />

這部分我找了很多資料,最終參考了這個(gè) demo,然后改進(jìn)了下。
主要原理是:
js 的調(diào)用封裝如下:
// 調(diào)用csharp的方法封裝
export default class CsharpMethod {
constructor(command, data) {
this.RequestPrefix = "request_csharp_";
this.ResponsePrefix = "response_csharp_";
// 唯一
this.dataId = this.RequestPrefix + new Date().getTime();
// 調(diào)用csharp的命令
this.command = command;
// 參數(shù)
this.data = { command: command, data: !data ? '' : JSON.stringify(data), key: this.dataId }
}
// 調(diào)用csharp 返回promise
call() {
// 把data存儲到localstorage中 目的是讓csharp端獲取參數(shù)
localStorage.setItem(this.dataId, this.utf8_to_b64(JSON.stringify(this.data)));
let eventKey = this.dataId.replace(this.RequestPrefix, this.ResponsePrefix);
let that = this;
const promise = new Promise(function (resolve, reject) {
const eventHandler = function (e) {
window.removeEventListener(eventKey, eventHandler);
let resp = e.newValue;
if (resp) {
// 從base64轉(zhuǎn)換
let realData = that.b64_to_utf8(resp);
if (realData.startsWith('err:')) {
reject(realData.substr(4));
} else {
resolve(realData);
}
} else {
reject("unknown error :" + eventKey);
}
};
// 注冊監(jiān)聽回調(diào)(csharp端處理完發(fā)起的)
window.addEventListener(eventKey, eventHandler);
});
// 改變location 發(fā)送給csharp端
window.location = "/api/" + this.dataId;
return promise;
}
// 轉(zhuǎn)成base64 解決中文亂碼
utf8_to_b64(str) {
return window.btoa(unescape(encodeURIComponent(str)));
}
// 從base64轉(zhuǎn)過來 解決中文亂碼
b64_to_utf8(str) {
return decodeURIComponent(escape(window.atob(str)));
}
}
前端的使用方式
import CsharpMethod from '../../services/api'
// 發(fā)起調(diào)用csharp的chat事件函數(shù)
const method = new CsharpMethod("chat", {msg: message});
method.call() // call返回promise
.then(data =>{
// 拿到csharp端的返回后展示
onMessageHandler({
message: data,
username: 'Robot',
type: 'chat_message'
});
}).catch(err => {
alert(err);
});
csharp 端的處理:

這么封裝后,js 和 csharp 的互相調(diào)用就很方便了。
注冊好 chatgpt 后可以申請一個(gè) APIKEY。

API 封裝:
public static async Task<CompletionsResponse> GetResponseDataAsync(string prompt)
{
// Set up the API URL and API key
string apiUrl = "https://api.openai.com/v1/completions";
// Get the request body JSON
decimal temperature = decimal.Parse(Setting.Temperature, CultureInfo.InvariantCulture);
int maxTokens = int.Parse(Setting.MaxTokens, CultureInfo.InvariantCulture);
string requestBodyJson = GetRequestBodyJson(prompt, temperature, maxTokens);
// Send the API request and get the response data
return await SendApiRequestAsync(apiUrl, Setting.ApiKey, requestBodyJson);
}
private static string GetRequestBodyJson(string prompt, decimal temperature, int maxTokens)
{
// Set up the request body
var requestBody = new CompletionsRequestBody
{
Model = "text-davinci-003",
Prompt = prompt,
Temperature = temperature,
MaxTokens = maxTokens,
TopP = 1.0m,
FrequencyPenalty = 0.0m,
PresencePenalty = 0.0m,
N = 1,
Stop = "[END]",
};
// Create a new JsonSerializerOptions object with the IgnoreNullValues and IgnoreReadOnlyProperties properties set to true
var serializerOptions = new JsonSerializerOptions
{
IgnoreNullValues = true,
IgnoreReadOnlyProperties = true,
};
// Serialize the request body to JSON using the JsonSerializer.Serialize method overload that takes a JsonSerializerOptions parameter
return JsonSerializer.Serialize(requestBody, serializerOptions);
}
private static async Task<CompletionsResponse> SendApiRequestAsync(string apiUrl, string apiKey, string requestBodyJson)
{
// Create a new HttpClient for making the API request
using HttpClient client = new HttpClient();
// Set the API key in the request headers
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + apiKey);
// Create a new StringContent object with the JSON payload and the correct content type
StringContent content = new StringContent(requestBodyJson, Encoding.UTF8, "application/json");
// Send the API request and get the response
HttpResponseMessage response = await client.PostAsync(apiUrl, content);
// Deserialize the response
var responseBody = await response.Content.ReadAsStringAsync();
// Return the response data
return JsonSerializer.Deserialize<CompletionsResponse>(responseBody);
}
調(diào)用方式
var reply = await ChatService.GetResponseDataAsync('xxxxxxxxxx');
完整代碼參考~
在學(xué)習(xí) maui 的過程中,遇到問題我在 Microsoft Learn 提問,回答的效率很快,推薦大家試試看!

點(diǎn)我了解更多 MAUI 相關(guān)資料~
“?.NET?MAUI如何開發(fā)AI平臺ChatGPT的客戶端?”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)技術(shù)相關(guān)的知識可以關(guān)注群英網(wǎng)絡(luò)網(wǎng)站,小編每天都會為大家更新不同的知識。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:[email protected]進(jìn)行舉報(bào),并提供相關(guān)證據(jù),查實(shí)之后,將立刻刪除涉嫌侵權(quán)內(nèi)容。
猜你喜歡
這篇文章主要為大家詳細(xì)介紹了.NET6使用ImageSharp實(shí)現(xiàn)給圖片添加水印功能的相關(guān)資料,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
這篇文章主要為大家介紹了.Net執(zhí)行SQL存儲過程之易用輕量工具詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
這篇文章主要介紹了MessagePack?和System.Text.Json?序列化和反序列化性能及對比分析,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
這篇文章主要介紹了ASP.NET?Core按用戶等級授權(quán),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
在軟件開發(fā)過程中,有時(shí)候我們需要定時(shí)地檢查數(shù)據(jù)庫中的數(shù)據(jù),并在發(fā)現(xiàn)新增數(shù)據(jù)時(shí)觸發(fā)一個(gè)動(dòng)作。為了實(shí)現(xiàn)這個(gè)需求,本文我們在?.Net?7?下進(jìn)行一次簡單的演示。感興趣的可以了解一下
推薦內(nèi)容
相關(guān)標(biāo)簽
成為群英會員,開啟智能安全云計(jì)算之旅
立即注冊關(guān)注或聯(lián)系群英網(wǎng)絡(luò)
7x24小時(shí)售前:400-678-4567
7x24小時(shí)售后:0668-2555666
24小時(shí)QQ客服
群英微信公眾號
CNNIC域名投訴舉報(bào)處理平臺
服務(wù)電話:010-58813000
服務(wù)郵箱:[email protected]
投訴與建議:0668-2555555
Copyright ? QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版權(quán)所有
增值電信經(jīng)營許可證 : B1.B2-20140078 ICP核準(zhǔn)(ICP備案)粵ICP備09006778號 域名注冊商資質(zhì) 粵 D3.1-20240008