Skip to content

Commit

Permalink
Merge branch 'release/2.7'
Browse files Browse the repository at this point in the history
  • Loading branch information
iHTCboy committed Jun 24, 2023
2 parents f5225c7 + 00bb9fc commit 4947f0f
Show file tree
Hide file tree
Showing 15 changed files with 153 additions and 69 deletions.
25 changes: 16 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,13 @@ OpenAI ChatGPT app for iOS, iPadOS, macoS

#### 更新说明

最新版本 v2.6
最新版本 v2.7

- Support custom API URL.(支持自定义 API URL。)
- Set API timeout duration.(设置 API 超时时间。)
- Configure API model for individual chat rooms.(支持聊天室单独设置 API 模型。)
- Support more model choices (e.g., gpt-4-32k).(支持更多模型选择,如 gpt-4-32k 等。)
- Change icons to local images and differentiate gpt-4 icons.(将图标更改为本地图片并区分 gpt-4 图标。)
- Fix auto letter conversion issue with consecutive characters (e.g., in Chinese or Japanese).(修复连续输入字符时自动变为字母的问题,如中文或日文。)
- Streamlined output support. (支持流式输出)
- Added modules for gpt-3.5-turbo-16k, gpt-3.5-turbo-16k-061, and gpt-4-32k-0613. (增加模块,支持 gpt-3.5-turbo-16k、gpt-3.5-turbo-16k-061 和 gpt-4-32k-0613)
- Increased request timeout to 60 seconds to reduce timeout issues. (请求超时时间调整为 60 秒,减少请求超时问题)
- Switched to historical conversations, automatically scrolling to the latest content. (切换历史对话,默认滚动到最新的对话内容)
- Optimized several user experience details. (优化一些体验细节)


**支持功能**
Expand Down Expand Up @@ -73,7 +72,7 @@ TestFlight 下载地址:[https://testflight.apple.com/join/GR4BOt2M](https://t
- Mac Apple Silicon M1/M2+
- Mac Intel x86_64

- Mac 下载:[Releases](https://github.com/37iOS/iChatGPT/releases)
- Mac 下载:[Releases](https://github.com/37MobileTeam/iChatGPT/releases)


#### 2.3 Xcode 构建
Expand Down Expand Up @@ -102,11 +101,19 @@ TestFlight 下载地址:[https://testflight.apple.com/join/GR4BOt2M](https://t

#### 3.3 More Questions

- [New Issue](https://github.com/37iOS/iChatGPT/issues/new/choose)
- [New Issue](https://github.com/37MobileTeam/iChatGPT/issues/new/choose)


#### 3.4 历史更新功能

**v2.6:**
- Support custom API URL.(支持自定义 API URL。)
- Set API timeout duration.(设置 API 超时时间。)
- Configure API model for individual chat rooms.(支持聊天室单独设置 API 模型。)
- Support more model choices (e.g., gpt-4-32k).(支持更多模型选择,如 gpt-4-32k 等。)
- Change icons to local images and differentiate gpt-4 icons.(将图标更改为本地图片并区分 gpt-4 图标。)
- Fix auto letter conversion issue with consecutive characters (e.g., in Chinese or Japanese).(修复连续输入字符时自动变为字母的问题,如中文或日文。)

**v2.5:**
- Added chat room settings with Prompt and Temperature parameter configuration. (新增聊天室设置功能,支持 Prompt 和 Temperature 参数配置。)
- Display current conversation identifier in the history list. (历史对话列表增加显示当前对话标识。)
Expand Down
14 changes: 6 additions & 8 deletions iChatGPT.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -571,9 +571,8 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 2023.04.16;
CURRENT_PROJECT_VERSION = 2023.06.25;
DEVELOPMENT_ASSET_PATHS = "\"iChatGPT/Preview Content\"";
DEVELOPMENT_TEAM = "";
ENABLE_PREVIEWS = YES;
Expand All @@ -591,7 +590,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 2.6;
MARKETING_VERSION = 2.7;
PRODUCT_BUNDLE_IDENTIFIER = com.37iOS.iChatGPT;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand All @@ -611,9 +610,8 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 2023.04.16;
CURRENT_PROJECT_VERSION = 2023.06.25;
DEVELOPMENT_ASSET_PATHS = "\"iChatGPT/Preview Content\"";
DEVELOPMENT_TEAM = "";
ENABLE_PREVIEWS = YES;
Expand All @@ -631,7 +629,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 2.6;
MARKETING_VERSION = 2.7;
PRODUCT_BUNDLE_IDENTIFIER = com.37iOS.iChatGPT;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down Expand Up @@ -771,15 +769,15 @@
repositoryURL = "https://github.com/MacPaw/OpenAI.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 0.1.1;
minimumVersion = 0.2.2;
};
};
6DAA917E2943448D004ACD01 /* XCRemoteSwiftPackageReference "MarkdownText" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/shaps80/MarkdownText.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.0.0;
minimumVersion = 1.2.0;
};
};
/* End XCRemoteSwiftPackageReference section */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/shaps80/MarkdownText.git",
"state" : {
"revision" : "0dbef003e450a59283cefaed433bd267fff87e7f",
"version" : "1.0.1"
"revision" : "c5f5e3e7d2de5dbccd7756d6b4b3739fdf427c33",
"version" : "1.2.0"
}
},
{
"identity" : "openai",
"kind" : "remoteSourceControl",
"location" : "https://github.com/MacPaw/OpenAI.git",
"state" : {
"revision" : "c1ee239b20f97344bb50ffd24361740ce1963181",
"version" : "0.1.1"
"revision" : "b1161597810167a035ae403c81ac6f1a542e41f9",
"version" : "0.2.2"
}
},
{
Expand All @@ -36,13 +36,22 @@
"version" : "0.3.0"
}
},
{
"identity" : "swiftbackports",
"kind" : "remoteSourceControl",
"location" : "https://github.com/shaps80/SwiftBackports",
"state" : {
"revision" : "ddca6a237c1ba2291d5a3cc47ec8480ce6e9f805",
"version" : "1.0.3"
}
},
{
"identity" : "swiftuibackports",
"kind" : "remoteSourceControl",
"location" : "https://github.com/shaps80/SwiftUIBackports",
"state" : {
"revision" : "d9842f24656ff7c6116dc207b60f0b6d302a5a9a",
"version" : "1.9.0"
"revision" : "3042f0cf4b9f0d5b0bb08ad17f742a43bc4fdfc5",
"version" : "2.8.0"
}
},
{
Expand Down
2 changes: 1 addition & 1 deletion iChatGPT/AIChatView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ struct AIChatView: View {
ChatHistoryListView(isKeyPresented: $inputModel.isShowAllChatRoom, chatModel: chatModel, onComplete: { roomID in
if roomID != chatModel.roomID {
chatModel.resetRoom(roomID)
isScrollListTop.toggle()
chatModel.isScrollListBottom.toggle()
}
})
}
Expand Down
54 changes: 35 additions & 19 deletions iChatGPT/ChatAPISettingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ struct ChatAPISettingView: View {
@State private var apiHost = kDeafultAPIHost
@State private var apiKey = ""
@State private var maskedAPIKey = ""
@State private var apiTimeout = "\(kDeafultAPITimeout)"
@State private var apiTimeout = "\(Int(kDeafultAPITimeout))"
@State private var isStreamOutput = true

@State private var apiHostError = ""
@State private var apiKeyError = ""
Expand Down Expand Up @@ -47,6 +48,10 @@ struct ChatAPISettingView: View {
_apiTimeout = State(initialValue: lastTime)
}

if let obj = UserDefaults.standard.object(forKey: ChatGPTStreamOutput), let isStream = obj as? Bool {
_isStreamOutput = State(initialValue: isStream)
}

if let lastKey = lastOpenAIKey() {
_maskedAPIKey = State(initialValue: lastKey)
}
Expand Down Expand Up @@ -118,6 +123,12 @@ struct ChatAPISettingView: View {
}
}

Section(header: Text("Chats Streaming")) {
Toggle(isOn: $isStreamOutput) {
Text("Use streaming conversations")
}
}

aboutAppSection
}
.listStyle(GroupedListStyle())
Expand All @@ -137,7 +148,7 @@ struct ChatAPISettingView: View {
.onChange(of: selectedModel) { _ in
self.isDirty = validateSettings()
}
.onChange(of: [apiHost, apiKey, apiTimeout]) { _ in
.onChange(of: [apiHost, apiKey, apiTimeout, String(isStreamOutput)]) { _ in
self.isDirty = validateSettings()
}
.gesture(
Expand All @@ -161,6 +172,7 @@ struct ChatAPISettingView: View {
UserDefaults.standard.set(apiKey, forKey: ChatGPTOpenAIKey)
}
UserDefaults.standard.set(apiTimeout, forKey: ChatGPTAPITimeout)
UserDefaults.standard.set(isStreamOutput, forKey: ChatGPTStreamOutput)
isKeyPresented = false
chatModel.isRefreshSession = true
}
Expand Down Expand Up @@ -203,27 +215,31 @@ struct ChatAPISettingView: View {
}

private var aboutAppSection: some View {
Section(header: Text("About App".localized())) {
ScrollView {
VStack {
Text("v \(appVersion ?? "") (\(appSubVersion ?? ""))")
.font(.footnote)
.foregroundColor(.gray)
.padding(.bottom, 10)
Section(header: Text("About App")) {
VStack {
ScrollView {
VStack {
Text("v \(appVersion ?? "") (\(appSubVersion ?? ""))")
.font(.footnote)
.foregroundColor(.gray)
.padding(.bottom, 10)

Text(.init("Developer: 37 Mobile iOS Tech Team\nGitHub: https://github.com/37iOS/iChatGPT".localized()))
.font(.footnote)
.foregroundColor(.secondary)
.multilineTextAlignment(.center)
.padding(.bottom, 10)
Text(.init("Developer: 37 Mobile iOS Tech Team\nGitHub: https://github.com/37iOS/iChatGPT".localized()))
.font(.footnote)
.foregroundColor(.secondary)
.multilineTextAlignment(.center)
.padding(.bottom, 10)

Text("Contributors:[@iHTCboy](https://github.com/iHTCboy) | [@AlphaGogoo](https://github.com/AlphaGogoo) | [@RbBtSn0w](https://github.com/RbBtSn0w) | [@0xfeedface1993](https://github.com/0xfeedface1993)")
.font(.footnote)
.foregroundColor(.secondary)
.multilineTextAlignment(.center)
Text("Contributors:[@iHTCboy](https://github.com/iHTCboy) | [@AlphaGogoo](https://github.com/AlphaGogoo) | [@RbBtSn0w](https://github.com/RbBtSn0w) | [@0xfeedface1993](https://github.com/0xfeedface1993)")
.font(.footnote)
.foregroundColor(.secondary)
.multilineTextAlignment(.center)
.padding(.bottom, 25)
}
}
.frame(maxHeight: 120)
}
.frame(maxHeight: 120)
.frame(maxWidth: .infinity, alignment: .center)
}
}
}
11 changes: 9 additions & 2 deletions iChatGPT/Models/AIChatModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ let ChatGPTOpenAIKey = "ChatGPTOpenAIKey"
let ChatGPTModelName = "ChatGPTModelName"
let ChatGPTAPIHost = "ChatGPTAPIHost"
let ChatGPTAPITimeout = "ChatGPTAPITimeout"
let ChatGPTStreamOutput = "ChatGPTStreamOutput"

// MARK: - Model
struct AIChat: Codable {
Expand All @@ -26,6 +27,8 @@ class AIChatModel: ObservableObject {
@Published var isScrollListBottom: Bool = true
/// 请求是否带上之前的提问和问答
@Published var isSendContext: Bool = true
/// 使用流式输出
@Published var isStreamOutput: Bool = true
/// 对话内容模型
@Published var contents: [AIChat] = [] {
didSet {
Expand Down Expand Up @@ -72,11 +75,12 @@ class AIChatModel: ObservableObject {
contents.append(chat)
isScrollListBottom.toggle()

self.bot?.getChatGPTAnswer(prompts: contents, sendContext: isSendContext, roomModel: roomModel) { answer in
self.bot?.getChatGPTAnswer(prompts: contents, sendContext: isSendContext, isStream: isStreamOutput, roomModel: roomModel) { answer in
let content = answer
DispatchQueue.main.async { [self] in
chat.answer = content
chat.answer = "\(chat.answer ?? "")\(content)"
chat.isResponse = true
isScrollListBottom.toggle()
// 找到要替换的元素在数组中的索引位置
if let index = contents.lastIndex(where: { $0.datetime == chat.datetime && $0.issue == chat.issue }) {
contents[index] = chat
Expand All @@ -91,6 +95,9 @@ class AIChatModel: ObservableObject {
let apiTimeout = TimeInterval(UserDefaults.standard.string(forKey: ChatGPTAPITimeout) ?? "") ?? kDeafultAPITimeout
let apiHost = UserDefaults.standard.string(forKey: ChatGPTAPIHost)
bot = Chatbot(openAIKey: apiKey, timeout: apiTimeout, host: apiHost)
if let obj = UserDefaults.standard.object(forKey: ChatGPTStreamOutput), let isStream = obj as? Bool {
isStreamOutput = isStream
}
}

func saveMessagesData() {
Expand Down
63 changes: 47 additions & 16 deletions iChatGPT/Models/ChatGPT.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import Combine
import OpenAI

let kDeafultAPIHost = "api.openai.com"
let kDeafultAPITimeout = 30.0
let kAPIModels = [Model.gpt3_5Turbo, Model.gpt4, Model.gpt4_32k, Model.gpt4_0314, Model.gpt4_32k_0314, Model.gpt3_5Turbo0301]
let kDeafultAPITimeout = 60.0
let kAPIModels = [Model.gpt3_5Turbo, Model.gpt4, Model.gpt4_32k, Model.gpt4_32k_0314, Model.gpt4_32k_0613, Model.gpt3_5Turbo_16k, Model.gpt3_5Turbo_16k_0613]

class Chatbot {
var timeout: TimeInterval = 60
Expand All @@ -31,7 +31,7 @@ class Chatbot {
userAvatarUrl
}

func getChatGPTAnswer(prompts: [AIChat], sendContext: Bool, roomModel: ChatRoom?, completion: @escaping (String) -> Void) {
func getChatGPTAnswer(prompts: [AIChat], sendContext: Bool, isStream: Bool, roomModel: ChatRoom?, completion: @escaping (String) -> Void) {
// 构建对话记录
print("prompts")
print(prompts)
Expand Down Expand Up @@ -60,20 +60,51 @@ class Chatbot {
let model = prompts.last?.model ?? "gpt-3.5-turbo"
print("model:")
print(model)
openAI.chats(query: .init(model: model, messages: messages, temperature: roomModel?.temperature ?? 0.7)) { result in
print("data:")
print(result)
switch result {
case .success(let chatResult):
let res = chatResult.choices.first?.message.content
DispatchQueue.main.async {
completion(res ?? "Unknown Error.")
let query = ChatQuery.init(model: model, messages: messages, temperature: roomModel?.temperature ?? 0.7)
// Chats Streaming
if isStream {
openAI.chatsStream(query: query) { partialResult in
switch partialResult {
case .success(let chatResult):
//print(chatResult.choices)
if let res = chatResult.choices.first?.delta.content {
DispatchQueue.main.async {
completion(res)
}
}
case .failure(let error):
//Handle chunk error here
print(error)
let errorMessage = error.localizedDescription
DispatchQueue.main.async {
completion(errorMessage)
}
}
case .failure(let error):
print(error)
let errorMessage = error.localizedDescription
DispatchQueue.main.async {
completion(errorMessage)
} completion: { error in
//Handle streaming error here
print(error ?? "Unknown Error.")
if let errorMessage = error?.localizedDescription {
DispatchQueue.main.async {
completion(errorMessage)
}
}
}
} else {
openAI.chats(query: query) { result in
print("data:")
print(result)
switch result {
case .success(let chatResult):
let res = chatResult.choices.first?.message.content
DispatchQueue.main.async {
completion(res ?? "Unknown Error.")
}
case .failure(let error):
print(error)
let errorMessage = error.localizedDescription
DispatchQueue.main.async {
completion(errorMessage)
}
}
}
}
Expand Down
Loading

0 comments on commit 4947f0f

Please sign in to comment.