Skip to content

Commit

Permalink
feat(docs): Documentation and small fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
gluonfield committed Dec 14, 2023
1 parent c6fdced commit 625e6d5
Show file tree
Hide file tree
Showing 10 changed files with 89 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<key>Enchanted.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
<integer>1</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
Expand Down
17 changes: 10 additions & 7 deletions Enchanted/Stores/ConversationStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ final class ConversationStore {

print(conversation.name)
print(conversation.messages)
print(conversation.model?.name ?? "")

let userMessage = MessageSD(content: userPrompt, role: "user")
userMessage.conversation = conversation
Expand Down Expand Up @@ -108,15 +109,17 @@ final class ConversationStore {

// @MainActor
private func handleReceive(_ response: OKChatResponse) {
if messages.isEmpty { return }

let lastIndex = messages.count - 1
let currentContent = messages[lastIndex].content
DispatchQueue.main.async { [self] in
if messages.isEmpty { return }

let lastIndex = messages.count - 1
let currentContent = messages[lastIndex].content

if let responseContent = response.message?.content {
messages[lastIndex].content = currentContent + responseContent
if let responseContent = response.message?.content {
messages[lastIndex].content = currentContent + responseContent
}
conversationState = .loading
}
conversationState = .loading
}

// @MainActor
Expand Down
6 changes: 6 additions & 0 deletions Enchanted/Stores/LanguageModelStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,17 @@ import SwiftData
final class LanguageModelStore {
private var swiftDataService: SwiftDataService
var models: [LanguageModelSD] = []
var selectedModel: LanguageModelSD?

init(swiftDataService: SwiftDataService) {
self.swiftDataService = swiftDataService
}

@MainActor
func setModel(model: LanguageModelSD?) {
selectedModel = model
}

@MainActor
func loadModels() async throws {
print("loading models")
Expand Down
12 changes: 5 additions & 7 deletions Enchanted/UI/Views/Chat/ChatView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ struct ChatView: View {
conversation: ConversationSD? = nil,
messages: [MessageSD],
modelsList: [LanguageModelSD],
selectedModel: LanguageModelSD?,
onMenuTap: @escaping () -> Void,
onNewConversationTap: @escaping () -> Void,
onSendMessageTap: @MainActor @escaping (_ prompt: String, _ model: LanguageModelSD) -> Void,
Expand All @@ -42,12 +43,7 @@ struct ChatView: View {
self.conversationState = conversationState
self.onStopGenerateTap = onStopGenerateTap
self.reachable = reachable

if let model = conversation?.model {
self._selectedModel = State(initialValue: model)
} else if modelsList.count > 0 {
self._selectedModel = State(initialValue: modelsList.first)
}
self.selectedModel = selectedModel
}

var header: some View {
Expand Down Expand Up @@ -203,7 +199,8 @@ struct ChatView: View {
ChatView(
conversation: ConversationSD.sample[0],
messages: MessageSD.sample,
modelsList: LanguageModelSD.sample,
modelsList: LanguageModelSD.sample,
selectedModel: LanguageModelSD.sample[0],
onMenuTap: {},
onNewConversationTap: { },
onSendMessageTap: {_,_ in},
Expand All @@ -219,6 +216,7 @@ struct ChatView: View {
conversation: nil,
messages: [],
modelsList: LanguageModelSD.sample,
selectedModel: LanguageModelSD.sample[0],
onMenuTap: {},
onNewConversationTap: { },
onSendMessageTap: {_,_ in},
Expand Down
3 changes: 2 additions & 1 deletion Enchanted/UI/Views/Chat/Components/MessageListVIew.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ struct MessageListView: View {
var body: some View {
ScrollViewReader { scrollViewProxy in
List(messages.indices, id:\.self) { index in
let roleName = messages[index].role == "user" ? "AM" : "AI"
// let roleName = messages[index].role == "user" ? "AM" : "AI"
let roleName = "assistant"
ChatMessageView(avatarName: roleName, name: messages[index].role, text: messages[index].content)
.id(messages[index])
.listRowInsets(EdgeInsets())
Expand Down
2 changes: 2 additions & 0 deletions Enchanted/UI/Views/Main/MainView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ struct MainView: View {
withAnimation(.bouncy(duration: 0.3)) {
do {
try conversationStore.selectConversation(conversation)
languageModelStore.selectedModel = conversation.model
} catch {

}
Expand Down Expand Up @@ -57,6 +58,7 @@ struct MainView: View {
conversation: conversationStore.selectedConversation,
messages: conversationStore.messages,
modelsList: languageModelStore.models,
selectedModel: languageModelStore.selectedModel,
onMenuTap: toggleMenu,
onNewConversationTap: newConversation,
onSendMessageTap: sendMessage,
Expand Down
59 changes: 58 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,58 @@
TBD
![Enchanted banner](./assets/banner.png)

# Enchanted

Enchanted is open source, [Ollama](https://github.com/jmorganca/ollama) compatible, elegant iOS/iPad mobile app for chatting with privately hosted models such as Llama 2, Mistral, Vicuna, Starling and more. It's essentially ChatGPT app UI that connects to your private Ollama models. You can download Enchanted from the App Store or build yourself from scratch.

## App Store

While app is being approved by Apple you can use Testflight beta invite link [here](https://testflight.apple.com/join/hs3N11rZ).

## Demo

[<img src="./assets/promo.png">](https://www.youtube.com/watch?v=3nGlMjVYYbE)

## Features

- Supports latest Ollama Chat API
- Conversation history included in the API calls
- Dark/Light mode
- Conversation history is stored on your device
- Markdown support (nicely displays tables/lists/code blocks)

### Comming soon

- Voice prompts
- Image attachments for prompts
- Download new models from mobile
- Manage your conversations (delete/rename)

## Usage instructions

Enchanted requires Ollama v0.1.14 or later.

### Case 1. You run Ollama server with public access

1. Download Enchanted app from the App Store.
2. In App Setings specify your server endpoint.

You're done! Make a prompt.

### Case 2. You run Ollama on your computer

[Video instructions here](https://www.youtube.com/watch?v=SFeVCiLOABM)

1. Start Ollama server and download models for usage.
2. Install ngrok forward your Ollama server to make it accessible publicly

```shell
ngrok http 11434
```

3. Copy "Forwarding" URL that will look something like `https://b377-82-132-216-51.ngrok-free.app`. Your Ollama server API is now accessible through this temporary URL.
4. Download Enchanted app from the App Store.
5. In App Setings specify your server endpoint.

You're done! Make a prompt.

## About me
5 changes: 5 additions & 0 deletions SUPPORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Support

Enchanted is an open source project and collaborators are very welcome.

For support please create a Github issue or contact me at [email protected].
Binary file added assets/banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/promo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 625e6d5

Please sign in to comment.