|
| 1 | +import CopilotForXcodeKit |
| 2 | +import Foundation |
| 3 | +import Fundamental |
| 4 | + |
| 5 | +/// https://ollama.com/library/codellama |
| 6 | +struct CodeLlamaFillInTheMiddleRequestStrategy: RequestStrategy { |
| 7 | + var sourceRequest: SuggestionRequest |
| 8 | + var prefix: [String] |
| 9 | + var suffix: [String] |
| 10 | + |
| 11 | + var shouldSkip: Bool { |
| 12 | + prefix.last?.trimmingCharacters(in: .whitespaces) == "}" |
| 13 | + } |
| 14 | + |
| 15 | + func createPrompt() -> Prompt { |
| 16 | + Prompt( |
| 17 | + sourceRequest: sourceRequest, |
| 18 | + prefix: prefix, |
| 19 | + suffix: suffix |
| 20 | + ) |
| 21 | + } |
| 22 | + |
| 23 | + func createRawSuggestionPostProcessor() -> NoOpRawSuggestionPostProcessingStrategy { |
| 24 | + NoOpRawSuggestionPostProcessingStrategy() |
| 25 | + } |
| 26 | + |
| 27 | + enum Tag { |
| 28 | + public static let prefix = "<PRE>" |
| 29 | + public static let suffix = "<SUF>" |
| 30 | + public static let middle = "<MID>" |
| 31 | + } |
| 32 | + |
| 33 | + struct Prompt: PromptStrategy { |
| 34 | + fileprivate(set) var systemPrompt: String = "" |
| 35 | + var sourceRequest: SuggestionRequest |
| 36 | + var prefix: [String] |
| 37 | + var suffix: [String] |
| 38 | + var filePath: String { sourceRequest.relativePath ?? sourceRequest.fileURL.path } |
| 39 | + var relevantCodeSnippets: [RelevantCodeSnippet] { sourceRequest.relevantCodeSnippets } |
| 40 | + var stopWords: [String] { ["\n\n", "<EOT>"] } |
| 41 | + var language: CodeLanguage? { sourceRequest.language } |
| 42 | + |
| 43 | + var suggestionPrefix: SuggestionPrefix { |
| 44 | + guard let prefix = prefix.last else { return .empty } |
| 45 | + return .unchanged(prefix).curlyBracesLineBreak() |
| 46 | + } |
| 47 | + |
| 48 | + func createPrompt( |
| 49 | + truncatedPrefix: [String], |
| 50 | + truncatedSuffix: [String], |
| 51 | + includedSnippets: [RelevantCodeSnippet] |
| 52 | + ) -> [PromptMessage] { |
| 53 | + let suffix = truncatedSuffix.joined() |
| 54 | + return [ |
| 55 | + .init( |
| 56 | + role: .user, |
| 57 | + content: """ |
| 58 | + \(Tag.prefix) // File Path: \(filePath) |
| 59 | + // Indentation: \ |
| 60 | + \(sourceRequest.indentSize) \ |
| 61 | + \(sourceRequest.usesTabsForIndentation ? "tab" : "space") |
| 62 | + \(includedSnippets.map(\.content).joined(separator: "\n\n")) |
| 63 | + \(truncatedPrefix.joined()) \ |
| 64 | + \(Tag.suffix)\(suffix.isEmpty ? "\n// End of file" : suffix) \ |
| 65 | + \(Tag.middle) |
| 66 | + """.trimmingCharacters(in: .whitespacesAndNewlines) |
| 67 | + ), |
| 68 | + ] |
| 69 | + } |
| 70 | + } |
| 71 | +} |
| 72 | + |
| 73 | +struct CodeLlamaFillInTheMiddleWithSystemPromptRequestStrategy: RequestStrategy { |
| 74 | + let strategy: CodeLlamaFillInTheMiddleRequestStrategy |
| 75 | + |
| 76 | + init(sourceRequest: SuggestionRequest, prefix: [String], suffix: [String]) { |
| 77 | + strategy = .init(sourceRequest: sourceRequest, prefix: prefix, suffix: suffix) |
| 78 | + } |
| 79 | + |
| 80 | + func createPrompt() -> some PromptStrategy { |
| 81 | + var prompt = strategy.createPrompt() |
| 82 | + prompt.systemPrompt = """ |
| 83 | + You are a senior programer who take the surrounding code and \ |
| 84 | + references from the codebase into account in order to write high-quality code to \ |
| 85 | + complete the code enclosed in the given code. \ |
| 86 | + You only respond with code that works and fits seamlessly with surrounding code. \ |
| 87 | + Don't include anything else beyond the code. \ |
| 88 | + The prefix will follow the PRE tag and the suffix will follow the SUF tag. \ |
| 89 | + You should write the code that fits seamlessly after the MID tag. |
| 90 | + """.trimmingCharacters(in: .whitespacesAndNewlines) |
| 91 | + |
| 92 | + return prompt |
| 93 | + } |
| 94 | + |
| 95 | + func createRawSuggestionPostProcessor() -> some RawSuggestionPostProcessingStrategy { |
| 96 | + DefaultRawSuggestionPostProcessingStrategy(openingCodeTag: "", closingCodeTag: "") |
| 97 | + } |
| 98 | +} |
| 99 | + |
0 commit comments