forked from intitni/CopilotForXcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDynamicContextController.swift
More file actions
94 lines (84 loc) · 3.09 KB
/
DynamicContextController.swift
File metadata and controls
94 lines (84 loc) · 3.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import ChatContextCollector
import Foundation
import OpenAIService
import Preferences
import XcodeInspector
final class DynamicContextController {
let contextCollectors: [ChatContextCollector]
let memory: AutoManagedChatGPTMemory
let functionProvider: ChatFunctionProvider
let configuration: ChatGPTConfiguration
var defaultScopes = [] as Set<String>
convenience init(
memory: AutoManagedChatGPTMemory,
functionProvider: ChatFunctionProvider,
configuration: ChatGPTConfiguration,
contextCollectors: ChatContextCollector...
) {
self.init(
memory: memory,
functionProvider: functionProvider,
configuration: configuration,
contextCollectors: contextCollectors
)
}
init(
memory: AutoManagedChatGPTMemory,
functionProvider: ChatFunctionProvider,
configuration: ChatGPTConfiguration,
contextCollectors: [ChatContextCollector]
) {
self.memory = memory
self.functionProvider = functionProvider
self.configuration = configuration
self.contextCollectors = contextCollectors
}
func updatePromptToMatchContent(systemPrompt: String, content: String) async throws {
var content = content
var scopes = Self.parseScopes(&content)
scopes.formUnion(defaultScopes)
functionProvider.removeAll()
let language = UserDefaults.shared.value(for: \.chatGPTLanguage)
let oldMessages = await memory.history
let contexts = await withTaskGroup(
of: ChatContext.self
) { [scopes, content, configuration] group in
for collector in contextCollectors {
group.addTask {
await collector.generateContext(
history: oldMessages,
scopes: scopes,
content: content,
configuration: configuration
)
}
}
var contexts = [ChatContext]()
for await context in group {
contexts.append(context)
}
return contexts
}
let extraSystemPrompt = contexts
.map(\.systemPrompt)
.filter { !$0.isEmpty }
.joined(separator: "\n\n")
let contextPrompts = contexts
.flatMap(\.retrievedContent)
.filter { !$0.content.isEmpty }
.sorted { $0.priority > $1.priority }
let contextualSystemPrompt = """
\(language.isEmpty ? "" : "You must always reply in \(language)")
\(systemPrompt)\(extraSystemPrompt.isEmpty ? "" : "\n\(extraSystemPrompt)")
"""
await memory.mutateSystemPrompt(contextualSystemPrompt)
await memory.mutateRetrievedContent(contextPrompts.map(\.content))
functionProvider.append(functions: contexts.flatMap(\.functions))
}
}
extension DynamicContextController {
static func parseScopes(_ prompt: inout String) -> Set<String> {
let parser = MessageScopeParser()
return parser(&prompt)
}
}