|
| 1 | +import AppKit |
1 | 2 | import LangChain |
2 | 3 | import OpenAIService |
3 | 4 | import PlaygroundSupport |
4 | 5 | import SwiftUI |
5 | 6 |
|
6 | | -let memory = ConversationChatGPTMemory(systemPrompt: "") |
7 | | -let chatGPTConfiguration = UserPreferenceChatGPTConfiguration().overriding { |
8 | | - $0.temperature = 0.2 |
9 | | -} |
| 7 | +struct QAForm: View { |
| 8 | + @State var intermediateAnswers = [String]() |
| 9 | + @State var answer: String = "" |
| 10 | + @State var question: String = "What is Swift macros?" |
| 11 | + @State var isProcessing: Bool = false |
| 12 | + @State var url: String = "https://developer.apple.com/documentation/swift/applying-macros" |
| 13 | + |
| 14 | + var body: some View { |
| 15 | + Form { |
| 16 | + Section(header: Text("Input")) { |
| 17 | + TextField("URL", text: $url) |
| 18 | + TextField("Question", text: $question) |
| 19 | + Button("Ask") { |
| 20 | + Task { |
| 21 | + do { |
| 22 | + try await ask() |
| 23 | + } catch { |
| 24 | + answer = error.localizedDescription |
| 25 | + } |
| 26 | + } |
| 27 | + } |
| 28 | + .disabled(isProcessing) |
| 29 | + } |
| 30 | + Section(header: Text("Answer")) { |
| 31 | + Text(answer) |
| 32 | + } |
| 33 | + Section(header: Text("Intermediate Answers")) { |
| 34 | + ForEach(intermediateAnswers, id: \.self) { answer in |
| 35 | + Text(answer) |
| 36 | + Divider() |
| 37 | + } |
| 38 | + } |
| 39 | + } |
| 40 | + .formStyle(.grouped) |
| 41 | + } |
10 | 42 |
|
11 | | -let embeddingConfiguration = UserPreferenceEmbeddingConfiguration().overriding() |
| 43 | + func ask() async throws { |
| 44 | + intermediateAnswers = [] |
| 45 | + isProcessing = true |
| 46 | + defer { isProcessing = false } |
| 47 | + guard let url = URL(string: url) else { |
| 48 | + answer = "Invalid URL" |
| 49 | + return |
| 50 | + } |
| 51 | + let chatGPTConfiguration = UserPreferenceChatGPTConfiguration() |
| 52 | + .overriding { $0.temperature = 0 } |
| 53 | + let embeddingConfiguration = UserPreferenceEmbeddingConfiguration().overriding() |
| 54 | + let embedding = OpenAIEmbedding(configuration: embeddingConfiguration) |
| 55 | + let store: VectorStore = try await { |
| 56 | + if let store = await TemporaryUSearch.view(identifier: url.absoluteString) { |
| 57 | + return store |
| 58 | + } else { |
| 59 | + let webLoader = WebLoader(urls: [url]) |
| 60 | + let store = TemporaryUSearch(identifier: url.absoluteString) |
| 61 | + let webDocuments = try await webLoader.load() |
| 62 | + let splitter = RecursiveCharacterTextSplitter( |
| 63 | + chunkSize: 1000, |
| 64 | + chunkOverlap: 100 |
| 65 | + ) |
| 66 | + let splitDocuments = try await splitter.transformDocuments(webDocuments) |
| 67 | + let embeddedDocuments = try await embedding.embed(documents: splitDocuments) |
| 68 | + try await store.set(embeddedDocuments) |
| 69 | + return store |
| 70 | + } |
| 71 | + }() |
12 | 72 |
|
13 | | -struct FakeVectorStore: VectorStore { |
14 | | - func add(_: [EmbeddedDocument]) async throws {} |
15 | | - func set(_: [EmbeddedDocument]) async throws {} |
16 | | - func clear() async throws {} |
17 | | - func searchWithDistance(embeddings: [Float], count: Int) async throws |
18 | | - -> [(document: Document, distance: Float)] |
19 | | - { |
20 | | - return [ |
21 | | - ( |
22 | | - document: .init( |
23 | | - pageContent: """ |
24 | | - Snoopy is an anthropomorphic beagle[5] in the comic strip Peanuts by Charles M. Schulz. He can also be found in all of the Peanuts films and television specials. Since his debut on October 4, 1950, Snoopy has become one of the most recognizable and iconic characters in the comic strip and is considered more famous than Charlie Brown in some countries. The original drawings of Snoopy were inspired by Spike, one of Schulz's childhood dogs. |
25 | | - """, |
26 | | - metadata: [:] |
27 | | - ), |
28 | | - distance: 0.2 |
29 | | - ), |
30 | | - ( |
31 | | - document: .init( |
32 | | - pageContent: """ |
33 | | - Snoopy is a loyal, imaginative, and good-natured beagle who is prone to imagining fantasy lives, including being an author, a college student known as "Joe Cool", an attorney, and a World War I flying ace. He is perhaps best known in this last persona, wearing an aviator's helmet and goggles and a scarf while carrying a swagger stick (like a stereotypical British Army officer of World War I and II). |
34 | | - """, |
35 | | - metadata: [:] |
36 | | - ), |
37 | | - distance: 0.2 |
38 | | - ), |
39 | | - ( |
40 | | - document: .init( |
41 | | - pageContent: """ |
42 | | - Snoopy can be selfish, gluttonous and lazy at times, and occasionally mocks his owner, Charlie Brown. But on the whole, he shows great love, care, and loyalty for his owner (even though he cannot even remember his name and always refers to him as "the round-headed kid"). In the 1990s comic strips, he is obsessed with cookies, particularly the chocolate-chip variety. This, and other instances in which he indulges in large chocolate-based meals and snacks, shows resistance to theobromine unheard of in other dogs. |
43 | | - """, |
44 | | - metadata: [:] |
45 | | - ), |
46 | | - distance: 0.2 |
47 | | - ), |
48 | | - ( |
49 | | - document: .init( |
50 | | - pageContent: """ |
51 | | - First appearance October 4, 1950 (comic strip) |
52 | | - Last appearance February 13, 2000 (comic strip) |
53 | | - Created by Charles M. Schulz |
54 | | - Voiced by |
55 | | - - Bill Melendez (1959–2008; 2015 archival recordings used in Peanuts Motion Comics, Snoopy's Grand Adventure,[1] and The Peanuts Movie) |
56 | | - - Bill Hinnant (1966; You're a Good Man, Charlie Brown)[2] |
57 | | - - Jim Campbell (1967; You're a Good Man, Charlie Brown)[3] |
58 | | - - Robert Towers (1985) |
59 | | - - Cam Clarke (1986–1989) |
60 | | - - Gerald Paradies (2002)[4] |
61 | | - - Andy Beall (2011) |
62 | | - - Dylan Jones (2018–present) |
63 | | - - Terry McGurrin (2019–present) |
64 | | - Aliases |
65 | | - - Joe Cool |
66 | | - - World Famous World War I Flying Ace |
67 | | - - The World's Greatest Writer |
68 | | - - The World Famous Attorney |
69 | | - - The World Famous Tennis Pro |
70 | | - Species Dog (Beagle) |
71 | | - Gender Male |
72 | | - Family |
73 | | - - Brothers: Spike, Andy, Olaf, Marbles, Rover |
74 | | - - Sisters: Belle, Molly |
75 | | - - Owner: Charlie Brown |
76 | | - - Sally Brown |
77 | | - - Lila (previously) |
78 | | - - Clara ("the annoying girl") |
79 | | - """, |
80 | | - metadata: [:] |
81 | | - ), |
82 | | - distance: 0.2 |
83 | | - ), |
84 | | - ] |
| 73 | + let qa = RetrievalQAChain( |
| 74 | + vectorStore: store, |
| 75 | + embedding: embedding, |
| 76 | + chatModelFactory: { OpenAIChat(configuration: chatGPTConfiguration, stream: false) } |
| 77 | + ) |
| 78 | + answer = try await qa.run( |
| 79 | + question, |
| 80 | + callbackManagers: [ |
| 81 | + .init { |
| 82 | + $0.on(CallbackEvents.RetrievalQADidGenerateIntermediateAnswer.self) { |
| 83 | + intermediateAnswers.append($0) |
| 84 | + } |
| 85 | + }, |
| 86 | + ] |
| 87 | + ) |
85 | 88 | } |
86 | 89 | } |
87 | 90 |
|
88 | | -let qa = RetrievalQAChain( |
89 | | - vectorStore: FakeVectorStore(), |
90 | | - embedding: OpenAIEmbedding(configuration: embeddingConfiguration), |
91 | | - chatModelFactory: { OpenAIChat(configuration: chatGPTConfiguration, stream: false) } |
| 91 | +let hostingView = NSHostingController( |
| 92 | + rootView: QAForm() |
| 93 | + .frame(width: 600, height: 800) |
92 | 94 | ) |
93 | 95 |
|
94 | | -let answer = try await qa.run("Who is the creator of Snoopy?") |
95 | | - |
96 | 96 | PlaygroundPage.current.needsIndefiniteExecution = true |
| 97 | +PlaygroundPage.current.liveView = hostingView |
97 | 98 |
|
0 commit comments