Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

System Prompts #70

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open

System Prompts #70

wants to merge 15 commits into from

Conversation

Niduank
Copy link
Collaborator

@Niduank Niduank commented Feb 12, 2025

Important to know

Old system message

We re-use the old system message as a default non-editable and non-removable SystemPrompt called outputOnly.
SystemPrompt.outputOnly is inserted in SwiftData at app launch if there is no entry.

Settings

List is sorted by timestamp desc
Search bar will filter on SystemPrompt[.name, .prompt, .tags] containing text
When deleting the selected SystemPrompt, we will try to select the most recently used one or outputOnly

ContentView

We always display/use a system prompt

Suggested System Prompt

The suggestions are displayed asynchronously.
Each SystemPrompt's suggestion is calculated based on a score.

For each application:
+5 for a match with the active (frontmost) application
+5 for a match with the input application (selected text)
+5 for a match with the applications from auto-context

For each tag:
+3 for a match in the input (selected text)
+3 for a match in auto-context and context files

Misc

  • New KeyboardShortcutManager which observe, enable/disable keyboard shortcuts
  • Changes on ModelContainer & EnvironmentValues
  • Script clean_app.sh updated - was not deleting default.store* files after backup

Base automatically changed from feature/streaming-support to main February 12, 2025 18:52
@Niduank Niduank force-pushed the feature/system-prompts branch from db3f201 to 0f14648 Compare February 13, 2025 10:38
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Summary

This PR implements a comprehensive system prompts feature with suggestion capabilities and keyboard shortcut integration.

  • Added SystemPromptSuggestionService in /macos/Onit/Data/Services/SystemPromptSuggestionService.swift that scores prompts based on app context and tags
  • Introduced SwiftDataContainer in /macos/Onit/Data/SwiftDataContainer.swift for managing persistent storage of Chat and SystemPrompt models
  • Added new UI components in /macos/Onit/UI/Prompt/SystemPrompt/ for managing and selecting system prompts
  • Centralized keyboard shortcut handling in /macos/Onit/KeyboardShortcuts/KeyboardShortcutsManager.swift
  • Improved cleanup script with safer file deletion logic in /macos/cleanup_app.sh

💡 (2/5) Greptile learns from your feedback when you react with 👍/👎!

39 file(s) reviewed, 41 comment(s)
Edit PR Review Bot Settings | Greptile

@@ -23,3 +23,7 @@ final class Chat {
prompts.map { $0.fullText }.joined(separator: "\n")
}
}

extension Chat {
@MainActor static let sample = Chat(prompts: [Prompt.sample])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Consider making sample private to prevent accidental usage in production code

Suggested change
@MainActor static let sample = Chat(prompts: [Prompt.sample])
@MainActor private static let sample = Chat(prompts: [Prompt.sample])

Comment on lines 12 to 15
"properties" : {
"preserves-vector-representation" : true
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Missing 'template-rendering-intent': 'template' property that's present in pencil.imageset. This icon won't adapt to UI color schemes like dark/light mode.

Suggested change
"properties" : {
"preserves-vector-representation" : true
}
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}

Comment on lines 27 to +28
init() {
KeyboardShortcuts.onKeyUp(for: .launch) { [weak model] in
let eventProperties: [String: Any] = [
"app_hidden": model?.panel == nil,
"highlight_hint_visible": HighlightHintWindowController.shared.isVisible(),
"highlight_hint_mode": FeatureFlagManager.shared.highlightHintMode,
]
PostHogSDK.shared.capture("shortcut_launch", properties: eventProperties)

model?.launchShortcutAction()
}
KeyboardShortcuts.onKeyUp(for: .toggleLocalMode) { [weak model] in
model?.toggleLocalVsRemoteShortcutAction()
}
KeyboardShortcuts.onKeyUp(for: .newChat) { [weak model] in
model?.newChat()
}
KeyboardShortcuts.onKeyUp(for: .resizeWindow) { [weak model] in
model?.resizeWindow()
}
KeyboardShortcuts.onKeyUp(for: .escape) { [weak model] in
model?.escapeAction()
}
KeyboardShortcuts.onKeyUp(for: .launchWithAutoContext) { [weak model] in
let eventProperties: [String: Any] = [
"app_hidden": model?.panel == nil
]
PostHogSDK.shared.capture(
"shortcut_launch_with_auto_context", properties: eventProperties)
model?.addAutoContext()
model?.launchPanel()
}
KeyboardShortcutsManager.configure(model: model)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: KeyboardShortcutsManager.configure() is called before model.showPanel(), but model is a weak reference in the manager. Consider reordering to ensure model is fully initialized

Comment on lines 19 to 21
systemPrompt = try container.mainContext.fetch(FetchDescriptor<SystemPrompt>())
.first(where: { $0.id == Defaults[.systemPromptId] }) ?? SystemPrompt.outputOnly
} catch {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: No error handling for database fetch failure - could silently use outputOnly without logging the error


let systemPrompt = prompt.systemPrompt ?? SystemPrompt.outputOnly
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Redundant fallback to SystemPrompt.outputOnly since it's already handled in prompt creation

Suggested change
let systemPrompt = prompt.systemPrompt ?? SystemPrompt.outputOnly
let systemPrompt = prompt.systemPrompt

Comment on lines 171 to 173
if !savedPrompt.applications.contains(url) {
savedPrompt.applications.append(url)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: redundant check - the allApps list is already filtered to exclude existing applications

Suggested change
if !savedPrompt.applications.contains(url) {
savedPrompt.applications.append(url)
}
savedPrompt.applications.append(url)

Comment on lines +45 to +46
Image(nsImage: NSWorkspace.shared.icon(forFile: url.path))
.resizable()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Loading app icons synchronously could cause UI stutter. Consider async loading with placeholder.

Comment on lines +101 to +107
KeyboardShortcuts.Recorder(
"Hotkey", name: KeyboardShortcuts.Name(savedPrompt.id)
) { shortcut in
if isSaved {
shortcutChanged.toggle()
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: keyboard shortcut changes are only tracked when prompt is saved, but not during initial creation - could lead to shortcut conflicts

prompts.filter {
$0.name.lowercased().contains(clearFilter) ||
$0.prompt.lowercased().contains(clearFilter) ||
$0.tags.joined(separator: ",").lowercased().contains(clearFilter)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: joined(separator: ",") creates a single string for tag search - could miss partial matches across tag boundaries

@@ -50,7 +50,7 @@ if [ -d "$DATABASE_PATH" ]; then
find "$DATABASE_PATH" -type f -name "default.store*" -exec cp {} "$BACKUP_DIR" \; > /dev/null 2>&1
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Consider adding -maxdepth option to find command to limit directory traversal depth

@timlenardo
Copy link
Contributor

Hi @Niduank - overall this looks great! I have one big behavioral change to request:

Since the system prompts are a special case that are inserted only at the beginning of the chat messages, we shouldn't be able to change the system prompt once after the first message. The prompt should show up only once at the top of the chat, and not be editable in the "Follow-up" field:

Screenshot 2025-02-18 at 1 37 54 PM

To use a different system prompt, users will have to start a new chat.

This might create a confusing experience, so I asked Elise to add a message explaining why the system prompt can't be edited (and a 'start new chat' button). Design is here

@Niduank Niduank force-pushed the feature/system-prompts branch from 96a1178 to 82449c3 Compare February 19, 2025 10:01
* List, add, edit, remove
* Search filters on name, prompt, tags
* Persist with SwiftData
* Added a non-editable and non-deletable default SystemPrompt called "outputResponse"
* Added the views SystemPromptView, SystemPromptSelectionView, and SystemPromptDetailView
* Selection persists in UserDefaults
* Used the selected prompt during a chat
* Changed the management of EnvironmentValues
* Changed the management of ModelContainer
* Updated the script that was not deleting default.store* files
* No need of SwiftData migration, we fallback on 'outputOnly'
* Save SystemPrompt in Prompt
* Display it in GeneratedView
* Added timestamp & lastUsed dates to SystemPrompt
* Sort SystemPrompts by timestamp in Settings & Selection
* When we remove the current system prompt, fallback to last used or outputOnly
* Fix random crash in Settings/SystemPrompt
* Display applications & tags correctly in a FlowLayout
* Set max width 400 to new system prompt form
* Frontmost application (apps)
* Input application (apps)
* Input selected text (tags)
* Auto context & file context (tags)
@Niduank Niduank force-pushed the feature/system-prompts branch from 1e0f069 to 9fcd050 Compare February 19, 2025 14:35
@Niduank
Copy link
Collaborator Author

Niduank commented Feb 19, 2025

Hi @Niduank - overall this looks great! I have one big behavioral change to request:

Since the system prompts are a special case that are inserted only at the beginning of the chat messages, we shouldn't be able to change the system prompt once after the first message. The prompt should show up only once at the top of the chat, and not be editable in the "Follow-up" field:

Screenshot 2025-02-18 at 1 37 54 PM To use a different system prompt, users will have to start a new chat.

This might create a confusing experience, so I asked Elise to add a message explaining why the system prompt can't be edited (and a 'start new chat' button). Design is here

@timlenardo I made the changes, everything works as expected.
Just to be sure, do we still need to send the system with each prompt?
If so, feel free to merge it 👍

@timlenardo
Copy link
Contributor

Hi @Niduank - Yes, the system prompt gets sent with each prompt, but it's static and always at the top of the message stack.

For example, if a user is sending a follow-up message, the stack will be:

System Prompt > 1st User Message > 1st LLM Reply > 2nd User message

@timlenardo
Copy link
Contributor

Hey Kevin - this looks great! There are a few changes to the header that should go along with this, as shown in this design.

Screenshot 2025-02-19 at 9 35 27 PM

Basically:

  • The 'full screen' button moves to the top right
  • The 'new chat' button moves to the left
  • There should be an arrow next to the 'new chat' button
  • By default, the system prompt UI should NOT appear.
  • If Onit has automatically changed the system prompt (due to Application or Keyword or something else) it should show the system prompt UI.
  • If the user hovers over the down button next to the "new chat" button, the System prompt UI appears.
  • If the user clicks the down button next to the "New chat" button, there's a window to "start new chat with system prompt" and shows the interface for choosing a system prompt.

Also, when the first time I ran this, I got a crash. It's worked on subsequent runs, but here's the crash I got:

Screenshot 2025-02-19 at 9 32 28 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants