微软跨平台maui开发chatgpt客户端
什么是maui
.NET 多平台应用 UI (.NET MAUI) 是一个跨平台框架,用于使用 C# 和 XAML 创建本机移动(ios,andriod)和桌面(windows,mac)应用。
chagpt
最近这玩意很火,由于网页版本限制了ip,还得必须开代理, 用起来比较麻烦,所以我尝试用maui开发一个聊天小应用 结合 chatgpt的开放api来实现(很多客户端使用网页版本接口用cookie的方式,有很多限制(如下图)总归不是很正规)
效果如下
mac端由于需要升级macos13才能开发调试,这部分我还没有完成,不过maui的控件是跨平台的,放在后续我升级系统再说
本项目开源
https://github.com/yuzd/maui_chatgpt
学习maui的老铁支持给个star
开发实战
我是设想开发一个类似jetbrains的ToolBox应用一样,启动程序在桌面右下角出现托盘图标,点击图标弹出应用(风格在windows mac平台保持一致)
需要实现的功能一览
托盘图标(右键点击有menu) webview(js和csharp互相调用) 聊天SPA页面(react开发,build后让webview展示)
新建一个maui工程(vs2022)
坑一: 默认编译出来的exe是直接双击打不开的
工程文件加上这个配置
<WindowsPackageType>None</WindowsPackageType>
<WindowsAppSDKSelfContained Condition="'$(IsUnpackaged)' == 'true'">true</WindowsAppSDKSelfContained>
<SelfContained Condition="'$(IsUnpackaged)' == 'true'">true</SelfContained>
以上修改后,编译出来的exe双击就可以打开了
托盘图标(右键点击有menu)
启动时设置窗口不能改变大小,隐藏titlebar, 让Webview控件占满整个窗口
这里要根据平台不同实现不同了,windows平台采用winAPI调用,具体看工程代码吧
WebView
在MainPage.xaml 添加控件
对应的静态html等文件放在工程的 Resource\Raw文件夹下 (整个文件夹里面默认是作为内嵌资源打包的,工程文件里面的如下配置起的作用)
<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
【重点】js和csharp互相调用
这部分我找了很多资料,最终参考了这个demo,然后改进了下
https://github.com/mahop-net/Maui.HybridWebView
主要原理是:
js调用csharp方法前先把数据存储在localstorage里 然后windows.location切换特定的url发起调用,返回一个promise,等待csharp的事件 csharp端监听webview的Navigating事件,异步进行下面处理 根据url解析出来localstorage的key 然后csharp端调用excutescript根据key拿到localstorage的value 进行逻辑处理后返回通过事件分发到js端
js的调用封装如下:
// 调用csharp的方法封装
export default class CsharpMethod {
constructor(command, data) {
this.RequestPrefix = "request_csharp_";
this.ResponsePrefix = "response_csharp_";
// 唯一
this.dataId = this.RequestPrefix + new Date().getTime();
// 调用csharp的命令
this.command = command;
// 参数
this.data = { command: command, data: !data ? '' : JSON.stringify(data), key: this.dataId }
}
// 调用csharp 返回promise
call() {
// 把data存储到localstorage中 目的是让csharp端获取参数
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转换
let realData = that.b64_to_utf8(resp);
if (realData.startsWith('err:')) {
reject(realData.substr(4));
} else {
resolve(realData);
}
} else {
reject("unknown error : " + eventKey);
}
};
// 注册监听回调(csharp端处理完发起的)
window.addEventListener(eventKey, eventHandler);
});
// 改变location 发送给csharp端
window.location = "/api/" + this.dataId;
return promise;
}
// 转成base64 解决中文乱码
utf8_to_b64(str) {
return window.btoa(unescape(encodeURIComponent(str)));
}
// 从base64转过来 解决中文乱码
b64_to_utf8(str) {
return decodeURIComponent(escape(window.atob(str)));
}
}
前端的使用方式
import CsharpMethod from '../../services/api'
// 发起调用csharp的chat事件函数
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的互相调用就很方便了
chatgpt的开放api调用
注册号chatgpt后可以申请一个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);
}
调用方式
var reply = await ChatService.GetResponseDataAsync('xxxxxxxxxx');
完整代码参考 https://github.com/yuzd/maui_chatgpt
在学习maui的过程中,遇到问题我在microsoft learn提问,回答的效率很快,推荐大家试试看
关于我
微软最有价值专家是微软公司授予第三方技术专业人士的一个全球奖项。27年来,世界各地的技术社区领导者,因其在线上和线下的技术社区中分享专业知识和经验而获得此奖项。
MVP是经过严格挑选的专家团队,他们代表着技术最精湛且最具智慧的人,是对社区投入极大的热情并乐于助人的专家。MVP致力于通过演讲、论坛问答、创建网站、撰写博客、分享视频、开源项目、组织会议等方式来帮助他人,并最大程度地帮助微软技术社区用户使用Microsoft技术。
更多详情请登录官方网站https://mvp.microsoft.com/zh-cn

微软跨平台maui开发chatgpt客户端的更多相关文章
- 新成员!Visual Studio Code --跨平台的开发工具(支持OSX, Linux 和 Windows)
原文出处:新成员!Visual Studio Code --跨平台的开发工具(支持OSX, Linux 和 Windows) 这是我的文章备份 http://www.dotblogs.com.tw/ ...
- 跨平台移动开发工具:PhoneGap与Titanium全方位比拼
PhoneGap和Appcelerator Titanium,对于封装和配置移动应用程序而言,二者都是非常受欢迎的开源JavaScript框架.本文为Appcelerator开发者Kevin Whin ...
- 前端开发福音!阿里Weex跨平台移动开发工具开源-b
阿里巴巴今天在Qcon大会上宣布跨平台移动开发工具Weex开放内测邀请.Weex能够完美兼顾性能与动态性,让移动开发者通过简捷的前端语法写出Native级别的性能体验,并支持iOS.安卓.YunOS及 ...
- 微软宣布.NET开发环境将开源 支持Mac OS X和Linux
微软宣布.NET开发环境将开源 支持Mac OS X和Linux 投递人 itwriter 发布于 2014-11-13 06:58 评论(55) 有4388人阅读 原文链接 [收藏] « » ...
- 微软宣布.NET开发环境将开源 支持三大操作系统(windows,Mac OS X和Linux)(转)
微软周三(11月12日)公布了.NET开发框架开源计划.公司拟将这长期以来只能运行于Windows系统下的开发环境,通过GitHub开源,以实现跨平台支持Mac OS X和Linux.根据微软公布的计 ...
- 带你从零学ReactNative开发跨平台App开发(六)
ReactNative跨平台开发系列教程: 带你从零学ReactNative开发跨平台App开发(一) 带你从零学ReactNative开发跨平台App开发(二) 带你从零学ReactNative开发 ...
- 微软发布了开发社区采用.NET Standard的最新信息
最近,微软发布了开发社区当前采用.NET Standard的最新信息..NET Standard是API的正式规范,现有.NET实现在不同平台的是通用的(从而允许跨平台开发).当前规范(版本2.0)在 ...
- Flutter与Xamarin跨平台移动开发相比
在过去十年中,移动行业经历了巨大的增长,特别是在应用程序开发方面.据Statista报告称,全球智能手机用户超过20亿,预计到2022年底这一数字将增加到50亿以上.在这些智能手机中,近100%在三个 ...
- [.net 面向对象程序设计深入](5)MVC 6 —— 构建跨平台.NET开发环境(Windows/Mac OS X/Linux)
[.net 面向对象程序设计深入](5)MVC 6 —— 构建跨平台.NET开发环境(Windows/Mac OS X/Linux) 1.关于跨平台 上篇中介绍了MVC的发展历程,说到ASP.NET ...
- Jsoup开发网站客户端第二篇,图片轮播,ScrollView兼容ListView
最近一段日子忙的焦头烂额,代码重构,新项目编码,导致jsoup开发网站客户端也没时间继续下去,只能利用晚上时间去研究了.今天实现美食网首页图片轮播效果,网站效果图跟Android客户端实现如图: 从浏 ...
随机推荐
- Kibana:如何周期性地为 Dashboard 生成 PDF Report
转载自:https://blog.csdn.net/UbuntuTouch/article/details/108449775 按照上面的方式填写.记得把之前的 URL 拷贝到 webhook 下的 ...
- 史上最全的selenium三大等待介绍
一.强制等待 1.设置完等待后不管有没有找到元素,都会执行等待,等待结束后才会执行下一步 2.实例 driver = webdriver.Chrome() driver.get("https ...
- aardio + Python 可视化快速开发桌面程序,一键生成独立 EXE
网络上大家分享的 aardio + Python 混合开发的文章很多,不得不说 aardio 与 Python 混合开发是真的简单 ! 快速入门 推荐几个快速上手教程:< aardio + P ...
- POJ3311 Hie with the Pie(状压DP,Tsp)
本题是经典的Tsp问题的变形,Tsp问题就是要求从起点出发经过每个节点一次再回到起点的距离最小值,本题的区别就是可以经过一个节点不止一次,那么先预处理出任意两点之间的最短距离就行了,因为再多走只会浪费 ...
- 一个好玩的deep learning Demo!
对于生活中的熟悉的动物,我们人脑经过一次扫描,便可以得到该动物的物种!那么机器是如何识别这个图片上的动物是属于哪一物种呢? 本次实验借生活中最常见的猫和狗来探究其原理! 环境准备: tensorflo ...
- React魔法堂:echarts-for-react源码略读
前言 在当前工业4.0和智能制造的产业升级浪潮当中,智慧大屏无疑是展示企业IT成果的最有效方式之一.然而其背后怎么能缺少ECharts的身影呢?对于React应用而言,直接使用ECharts并不是最高 ...
- Docker | redis安装及测试
此篇文章目的是熟悉一下redis的下载安装使用,为后面部署redis集群做准备. 下载安装 linux上,我在/download目录下,执行下载的命令 root@--- ~]# wget http:/ ...
- 2022年最新最详细的tomcat安装教程和常见问的解决
文章目录 1.官网直接下载 1.1.jdk的版本和tomcat版本应该相对应或者兼容 1.2. 在官网找对应的tomcat版本进行下载 1.3 .根据电脑版本下载64-bit windows zip( ...
- logback在springBoot项目中的使用 springboot中使用日志进行持久化保存日志信息
文章目录 1.xml文件的编写 2.实现的效果 2.1 日志保存到磁盘 2.2 控制台输出的效果 放置的位置 1.xml文件的编写 logback-spring.xml <?xml versio ...
- 创建外部表步骤及解决ORA-29913:执行ODCIETTABLEOPEN调出时出错
创建外部表步骤 建立目录对象(用sys用户创建.授权) 外部表所在路径一定要写对!!! create directory ext_data as 'D:\ORACLE'; grant read,wri ...