用 SwiftUI 实现 AI 聊天对话 app - iChatGPT

一、前言

关于 ChatGPT 的话题,大家都不陌生,我们直入话题,因为 ChatGPT 目前限制中国访问服务,所以如果直接使用 ChatGPT 网页进行对话,还是不太方便。通过 ChatGPT SessionToken 就可以不限制网络访问,所以大家发挥想象力实现各种的聊天机器人、小程序,而原生 app 可能体验更好!所以就有了 iChatGPT!一款用 SwiftUI 实现的开源 ChatGPT app,欢迎大家关注和提 PR。

二、iChatGPT

GitHub 开源地址:https://github.com/37iOS/iChatGPT

目前 v1.0.0,实现 ChatGPT 基本聊天功能:

  • 可以直接与 ChatGPT 对话,并且保留上下文;
  • 可以复制问题和回答内容;
  • 可以快捷重复提问等

支持系统:

  • iOS 14.0+
  • iPadOS 14.0+
  • macOS 11.0+

三、App 使用介绍

iChatGPT-02.jpeg

首先,需要点击 app 右上角图标,添加 ChatGPT SessionToken 密钥才能使用,否则无法请求。

iChatGPT-03.jpeg

获取 SessionToken 的方法很多,其中浏览器方法:

  1. 登录 https://chat.openai.com/chat
  2. 按 F12 打开控制台(macOS 可以用快捷键 command + option + I
  3. 切换到 Application(应用) 选项卡,找到 Cookies (Safari 浏览器是 储存空间 选项卡)
  4. 复制 __Secure-next-auth.session-token 的值,添加到 app 后确认。

iChatGPT-04.jpeg

操作的界面如下:

iChatGPT-05.jpeg

四、App 实现介绍

使用 SwiftUI 大概几个小时就完成所有的工作,方便跟苹果生态实现。实现的难点就可能就是模拟 ChatGPT 请求过程。目前是根据 A-kirami/nonebot-plugin-chatgpt 项目中的 python 实现,用 Swift 重写了一次,而 ChatGPT 登陆暂时没有实现,大家可以提 pr。

最后封装的网络请求类 ChatGPT.swift


class Chatbot {let apUrl = "https://chat.openai.com/"let sessionTokenKey = "__Secure-next-auth.session-token"let timeout = 30var sessionToken: Stringvar authorization = ""var conversationId = ""var parentId = ""let  id = ""init(sessionToken: String) {self.sessionToken = sessionToken}func headers() -> [String: String] {return ["Host": "chat.openai.com","Accept": "text/event-stream","Authorization": "Bearer \(self.authorization)","Content-Type": "application/json","User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15","X-Openai-Assistant-App-Id": "","Connection": "close","Accept-Language": "en-US,en;q=0.9","Referer": "https://chat.openai.com/chat",]}func getPayload(prompt: String) -> [String: Any] {var body = ["action": "next","messages": [["id": "\(UUID().uuidString)","role": "user","content": ["content_type": "text", "parts": [prompt]],]],"parent_message_id": "\(self.parentId)","model": "text-davinci-002-render",] as [String: Any]if !self.conversationId.isEmpty {body["conversation_id"] = self.conversationId}return body}func refreshSession() async {let cookies = "\(sessionTokenKey)=\(self.sessionToken)"let url = self.apUrl + "api/auth/session"let userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15"var request = URLRequest(url: URL(string: url)!)request.httpMethod = "GET"request.addValue(userAgent, forHTTPHeaderField: "User-Agent")request.addValue(cookies, forHTTPHeaderField: "Cookie")do {let (data, response) = try await URLSession.shared.data(for: request)let json = try JSONSerialization.jsonObject(with: data, options: [])if let dictionary = json as? [String: Any] {// Use the dictionary hereif let accessToken = dictionary["accessToken"] as? String {authorization = accessToken}}guard let response = response as? HTTPURLResponse,let cookies = HTTPCookieStorage.shared.cookies(for: response.url!) else {// handle errorprint("刷新会话失败: <r>HTTP:\(response)")return}for cookie in cookies {if cookie.name == sessionTokenKey {self.sessionToken = cookie.valueUserDefaults.standard.set(cookie.value, forKey: ChatGPTSessionTokenKey)}}}catch {print("刷新会话失败: <r>HTTP:\(error)")}}func getChatResponse(prompt: String) async -> String {if  self.authorization.isEmpty {await refreshSession()}let url = self.apUrl + "backend-api/conversation"var request = URLRequest(url: URL(string: url)!)request.httpMethod = "POST"request.allHTTPHeaderFields = headers()let dict = getPayload(prompt: prompt)do {let jsonData = try JSONSerialization.data(withJSONObject: dict, options: [])request.httpBody = jsonDatalet (data, response) = try await URLSession.shared.data(for: request)guard let response = response as? HTTPURLResponse else {let err = "非预期的响应内容:  <r>HTTP:\(response)"print(err)return err}if response.statusCode == 429 {return "请求过多,请放慢速度"}guard let text = String(data: data, encoding: .utf8) else {return "非预期的响应内容: 内容读取失败~"}if response.statusCode != 200 {let err = "非预期的响应内容:  <r>HTTP:\(response.statusCode)</r> \(text)"print(err)return err}let lines = text.components(separatedBy: "\n")// 倒数第四行,第6个字符后开始let str = lines[lines.count - 5]#if DEBUGprint(str)#endiflet jsonString = str.suffix(from: str.index(str.startIndex, offsetBy: 6))guard let jsondata = jsonString.data(using: .utf8) else {return ""}let json = try JSONSerialization.jsonObject(with: jsondata, options: [])guard let dictionary = json as? [String: Any],let conversation_id = dictionary["conversation_id"] as? String,let message = dictionary["message"] as? [String: Any],let parent_id = message["id"] as? String,let content = message["content"] as? [String: Any],let texts = content["parts"] as? [String],let parts = texts.lastelse {return "解析错误~"}self.parentId = parent_idself.conversationId = conversation_idreturn parts}catch {return "异常:\(error)"}}
}

唯一可以说说的就是,ChatGPT 的 backend-api/conversation 接口返回的内容,为了实现一个连接打开的效果,返回了一堆的数据。例如一个回答是 "我无法确定全球当前的人口数量,因为我没有浏览网页的能力。",返回的内容是这样:

data: {"message": {"id": "xxxx", "role": "assistant", "user": null, "create_time": null, "update_time": null, "content": {"content_type": "text", "parts": ["我"]}, "end_turn": null, "weight": 1.0, "metadata": {}, "recipient": "all"}, "conversation_id": "xxxx", "error": null}data: {"message": {"id": "xxxx", "role": "assistant", "user": null, "create_time": null, "update_time": null, "content": {"content_type": "text", "parts": ["我无"]}, "end_turn": null, "weight": 1.0, "metadata": {}, "recipient": "all"}, "conversation_id": "xxxx", "error": null}data: {"message": {"id": "xxxx", "role": "assistant", "user": null, "create_time": null, "update_time": null, "content": {"content_type": "text", "parts": ["我无法"]}, "end_turn": null, "weight": 1.0, "metadata": {}, "recipient": "all"}, "conversation_id": "xxxx", "error": null}中间省略xxxx行
中间省略xxxx行
中间省略xxxx行data: {"message": {"id": "xxxx", "role": "assistant", "user": null, "create_time": null, "update_time": null, "content": {"content_type": "text", "parts": ["我无法确定全球当前的人口数量,因为我没有浏览网页的能力"]}, "end_turn": null, "weight": 1.0, "metadata": {}, "recipient": "all"}, "conversation_id": "xxxx", "error": null}data: {"message": {"id": "xxxx", "role": "assistant", "user": null, "create_time": null, "update_time": null, "content": {"content_type": "text", "parts": ["我无法确定全球当前的人口数量,因为我没有浏览网页的能力。"]}, "end_turn": null, "weight": 1.0, "metadata": {}, "recipient": "all"}, "conversation_id": "xxxx", "error": null}

所以,需要按行分割,然后取倒数第四行的内容,再去掉 data: 字符才是我们想要的 json 内容。

let lines = text.components(separatedBy: "\n")
// 倒数第四行,第6个字符后开始
let str = lines[lines.count - 5]

当然,目前 ChatGPT 还是 beta 阶段,所以暂时没有开放 API,后续如果提供 API,就会更加方便!

五、ChatGPT 的一些问题

是否收费

目前 ChatGPT 是 beta 免费使用阶段,未来 API 请求会收费,具体可参考 https://openai.com/blog 。

修改头像

ChatGPT 对话的个人头像,大家发现无法有 https://openai.com 上进行修改。因为目前使用的是 Gravatar 服务。

Gravatar,全称 Globally Recognized Avatar。翻译成中文叫:全球通用头像。

Gravatar 的概念首先是在国外的独立 WordPress 博客中兴起的,当你到任何一个支持Gravatar的网站留言时,这个网站都会根据你所提供的Email地址为你显示出匹配的头像。当然,这个头像,是需要你事先到 Gravatar 的网站注册并上传的,否则,在这个网站上,就只会显示成一个默认的头像。

简单来说,就是头像链接为 https://s.gravatar.com/avatar/xxx,其中 xxx 就是你登陆邮箱的 MD5 值,只要在 Gravatar 注册验证了这个邮箱,你就可以更新头像,或者任何人都可以获取你的头像,只要知道你的邮箱。详细可以参考:Image Requests - Globally

有趣的对话

写一首诗,庆祝 iChatGPT app 开源:

iChatGPT-06.jpeg

咦,知道 iChatGPT 它酷炫极了,支持语言模型交互它开源了,人人可用快来下载,体验它的强大它可以帮助你,完成复杂任务不论是写文章,还是做研究它是程序员的好帮手让工作更高效,更愉快啦啦啦,iChatGPT 开源了,万岁!

直呼牛~

六、总结

目前 iChatGPT 开源地址:https://github.com/37iOS/iChatGPT 。还有很多功能没有实现,比如:

  • 保存对话
  • 显示个人头像
  • 代码没有高亮
  • 请求失败重试等等

欢迎大家提 PR !

另外,我们近期也会更新 AppleParty,更新苹果批量上传内购商品功能,敬请期待~

最后,大家觉得 ChatGPT 解决了什么痛点?有什么期待吗

欢迎大家评论区一起讨论交流~

欢迎关注我们,了解更多 iOS 和 Apple 的动态~

参考引用

  • 37iOS/iChatGPT - GitHub
  • OpenAI ChatGPT
  • OpenAI Blog
  • A-kirami/nonebot-plugin-chatgpt
  • Image Requests - Globally

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/9243.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

追赶ChatGPT,我们的差距在哪里?

又一家中国互联网巨头在追赶ChatGPT了。 3月底举行的博鳌亚洲论坛上&#xff0c;腾讯集团高级执行副总裁汤道生披露&#xff0c;腾讯正在研发AIGC以及大模型相关技术&#xff0c;类ChatGPT的对话机器人也在酝酿中。 百度、华为&#xff0c;如今再加上腾讯&#xff0c;ChatGPT出…

AI绘图新玩法「艺术风二维码」保姆级教程分享,注册账号就能玩,一分钟出图,定制自己的二维码!

部分图片有问题…可以看看这里。 大家好&#xff0c;我是卷了又没卷&#xff0c;薛定谔的卷的AI算法工程师「陈城南」~ 担任某大厂的算法工程师&#xff0c;带来最新的前沿AI知识和工具&#xff0c;包括AI相关技术、ChatGPT、AI绘图等&#xff0c;欢迎大家交流~。 最近AI绘图…

强力推荐:ChatGPT指令大全指南

担任记者 我想让你做一名记者。您将报道突发新闻&#xff0c;撰写专题报道和评论文章&#xff0c;开发用于验证信息和发现来源的研究技术&#xff0c;遵守新闻道德&#xff0c;并以您自己独特的风格提供准确的报道。我的第一个建议请求是“我需要帮助写一篇关于世界主要城市空气…

谈谈我对证券公司一些部门的理解——前、中、后台(转)

导语&#xff1a;起底金融界从业的主流选择。 作者 | cnfake 来源 | 经管之家&#xff08;原人大经济论坛&#xff09; 已经是2013年6月的一篇文章了&#xff0c;作者在文中对证券公司前中后台的各个部门的业务与职能&#xff0c;未来发展前景等方面进行了分析&#xff0c;笔者…

ChatGPT告诉你:项目管理能干到60岁吗?

早上好&#xff0c;我是老原。 这段时间最火的莫过于ChatGPT&#xff0c;从文章创作到论文写作&#xff0c;甚至编程序&#xff0c;简直厉害的不要不要的。 本以为过几天热度就自然消退了&#xff0c;结果是愈演愈烈&#xff0c;热度未减…… 大家也从一开始得玩乐心态&#xf…

微软将更新Bing整合更快速版本的ChatGPT

根据Semafor 报导&#xff0c;微软正致力于将OpenAI 的ChatGPT 的更快版本&#xff0c;引进Bing 搜索引擎&#xff0c;以此作为与Google 竞争的工具。知情人向Semafor 透露&#xff0c;ChatGPT 和GPT-4 之间的主要区别在于速度。虽然ChatGPT 有时需要几分钟才能产生回应&#x…

邮件客户端用IMAP还是POP3,为什么?Thunderbird 雷鸟和免费腾讯企业邮箱

从2023年4月1日起腾讯企业邮箱免费版的容量从2G降到1G&#xff0c;网易企业邮箱免费版也只有1G&#xff0c;所以现实的问题是如何把目前服务器上的所有邮件下载下来&#xff1f; 很久很久以前当网速很慢上网费很贵的时候一直使用POP3协议&#xff0c;这样可以Offline写邮件查邮…

通过预设ChatGPT指令让博弈Ai为你轻松的工作

链接&#xff1a;博弈Ai-基于ChatGPT4及3.5的智能聊天机器人国产镜像博弈Ai是一款基于OpenAI公司的ChatGPT4.0和3.5接口开发的国产镜像官网&#xff0c;可以对话、聆听、学习和挑战的自然语言生成式人工智能Ai聊天机器人&#xff0c;同时接入百度文心一言、阿里通义千问、华为盘…

ChatGPT API 低价上线,开发者可以人手一个了?

千呼万唤&#xff0c;ChatGPT API来了&#xff01; 不仅首发&#xff0c;价格居然还有惊喜&#xff0c;0.002美元/每1000 token&#xff0c;并将价格降低90%&#xff0c;直接打了1折。OpenAI官方还表示&#xff0c;gpt-3.5-turbo目前的版本代号是gpt-3.5-turbo-0301&#xff0…

ChatGPT 是怎样炼成的?

原本链接&#xff1a;https://mp.weixin.qq.com/s/R8EwUppkQg4igal_5h6E0Q 一、前言 2022 年 11 月&#xff0c;OpenAI 发布了大规模语言模型的又一力作&#xff1a;ChatGPT&#xff0c;瞬间引爆学术界和舆论场&#xff0c;有人用它编写贺词发送祝福&#xff0c;有人用它吟诗…

多云时代,下一代数据管理箭在弦上

“云服务提供商仅保护基础架构&#xff0c;客户负责保护自己的应用程序和数据。”这是很多云服务商都会遵从的云安全责任共担模型的一条基本原则。但实际上&#xff0c;只有3%的中国受访者知晓这一模式并认为上述说法是正确的。Veritas发布的《2022守护企业多云环境》研究报告的…

大模型生态和产业链分析,拆解OpenAI 的愿景和技术底层

本文从 OpenAI 的 AGI 愿景出发&#xff0c;对基于大模型的生态和产业链的发展给出了自己的分析并提出了一些供大家思考的问题。希能够对国内正在从事大模型研究、开发、投资的工作者们带来帮助。 社群讨论&#xff1a; ​ 原报告内容已"开源"并在持续更新中&#xf…

使用 Azure OpenAI 创建一个聊天机器人

由于众所周知的原因&#xff0c;国内是没法直接调用 OpenAI 接口的。幸好可以白嫖 Cloudfare Workers、Vercel 等免费服务做 API 代理&#xff0c;我之前一直是这么用的&#xff0c;速度也还可以。 前两天申请的微软的 Azure OpenAI 接口通过了&#xff0c;立即体验了一下。它的…

2023被裁三个月,海投一个月,从JAVA转战Android的求职之路!

前言 看到这个标题的童鞋&#xff0c;可能会想是Java开发不景气了吗&#xff1f;还是Android开发雄起了&#xff1f; 我是2019年6月份毕业&#xff0c;第一份工作是做JAVA开发。2023年3月初&#xff0c;我被公司优化掉了&#xff0c;从零开始&#xff0c;在家自学了两个月的A…

马斯克离开OpenAI内幕:大权独揽想法被拒,说好的10亿美元也打了水漂...

点击下方卡片&#xff0c;关注“CVer”公众号 AI/CV重磅干货&#xff0c;第一时间送达 点击进入—>【计算机视觉】微信技术交流群 作者&#xff1a;Reed Albergotti 转载自&#xff1a;机器之心 | 编辑&#xff1a;王楷 作为创始投资人&#xff0c;马斯克为什么和 OpenAI「反…

马斯克离开OpenAI内幕:大权独揽想法被拒,说好的10亿美元也打了水漂

选自semafor 作者&#xff1a;Reed Albergotti 机器之心编译 编辑&#xff1a;王楷 作为创始投资人&#xff0c;马斯克为什么和 OpenAI「反目成仇」&#xff1f; 在 OpenAI 成立三年之后&#xff0c;埃隆・马斯克准备放弃他扶持创立的这家人工智能研究公司。 OpenAI 于 2015 年…

【Prompting】ChatGPT Prompt Engineering开发指南(3)

ChatGPT Prompt Engineering开发指南3 总结文字使用单词/句子/字符限制进行总结以运输和交付为重点进行总结以价格和价值为重点进行总结 尝试“extract”而不是“summarize”总结多个产品评论内容来源 本文承接上文&#xff1a;ChatGPT Prompt Engineering开发指南2&#xff0c…

巴比特 | 元宇宙每日必读:承认ChatGPT正损害公司业务增长,美国知名在线教育公司股价一日腰斩,带崩欧美教育股...

摘要&#xff1a;据华尔街见闻报道&#xff0c;近日&#xff0c;美国知名在线教育公司Chegg的首席执行官Dan Rosenweig在财报电话会议上承认&#xff0c;ChatGPT正在损害其业务增长&#xff1a;“自3月份以来&#xff0c;我们发现学生对ChatGPT的兴趣显著上升。我们现在认为&am…

马斯克离开OpenAI内幕:大权独揽想法被拒

Datawhale干货 选自&#xff1a;Semafor&#xff0c;编译&#xff1a;机器之心 作为创始投资人&#xff0c;马斯克为什么和 OpenAI「反目成仇」&#xff1f; 在 OpenAI 成立三年之后&#xff0c;埃隆・马斯克准备放弃他扶持创立的这家人工智能研究公司。 OpenAI 于 2015 年成立…

纽约大学教授建议:ChatGPT时代下,请躺平!

文&#xff5c;小戏 二月以来一波一波的 ChatGPT 和 GPT-4 刷屏&#xff0c;从围城外面来看整个 AI 社区确实一片勃勃生机万物竞发&#xff0c;CNN、纽约客又一次开始讨论人工智能危机&#xff0c;公众号里“ChGPT时代&#xff0c;我们该如何如何”的文章也轻松拿到十万&#x…