Skip to content

Instantly share code, notes, and snippets.

@joelkuiper
Last active January 31, 2024 12:37
Show Gist options
  • Save joelkuiper/9397b196d032d33137b72a3ff65c5888 to your computer and use it in GitHub Desktop.
Save joelkuiper/9397b196d032d33137b72a3ff65c5888 to your computer and use it in GitHub Desktop.
Book checking with the ChatGPT API
#!/usr/bin/env bb
(require '[babashka.http-client :as client])
(require '[cheshire.core :as json])
(require '[babashka.fs :as fs])
(require '[clojure.string :as str])
(require '[babashka.process :refer [shell] :as p])
(defn read-edn-path
[path]
(read-string (slurp (str (fs/canonicalize (fs/expand-home path))))))
(def api-key (:openai-api-key (read-edn-path "~/.secrets.edn")))
(def prompts
(read-edn-path "./prompts.edn"))
(defn openai-complete
[request]
(let [response (client/post "https://api.openai.com/v1/chat/completions"
{:headers {"Content-Type" "application/json"
"Authorization" (str "Bearer " api-key)}
:body (json/generate-string request)})]
(get-in (json/parse-string (:body response) true)
[:choices 0 :message :content])))
(defn enumerate [coll]
(map-indexed (fn [index item] [index item]) coll))
(defn show-diff
[f1 f2]
(let [args ["diff" "--color=always" "--ignore-all-space" f1 f2]
result (-> (p/process {:out :string} (str/join " " args)) :out deref)]
(shell "clear")
(println result)
result))
(defn replace-quotes
[text]
(-> text
(str/replace #"\"([^\"]*)\"" "``$1''")))
(defn sentence-tokenize
[text]
(let [cmd (str/join " " ["python" (str (fs/canonicalize "sentence_tokenize.py"))])]
(-> @(p/process {:out :string :in text} cmd) :out)))
(def last-seenf ".last-seen")
(defn result-dir-path-fn
[result-dir f]
(str (fs/canonicalize (fs/path result-dir f))))
(defn ith-result
[result-dir idx]
(->
(result-dir-path-fn result-dir (format "result-%s.txt" idx))
(str)
(slurp)))
(defn process-part!
[result-dir system-prompt part n-parts idx]
(let [prompt (str/join "\n" part)
messages [{:role "system"
:content system-prompt}
#_{:role "user"
:content (if (> idx 1)
(str "Vorige gedachten:\n"
(if (> 2 idx)
(str (ith-result result-dir (- idx 2)) "\n"))
(ith-result result-dir (dec idx)))
"")}
{:role "user"
:content (str (format "Deel %d/%d.\n\n" idx n-parts) prompt)}]
result (openai-complete
{:model "gpt-4"
:messages messages})
prompt-file (result-dir-path-fn result-dir (format "prompt-%s.txt" idx))
result-file (result-dir-path-fn result-dir (format "result-%s.txt" idx))]
;; flush-result!
(println (format "Wrote %s" (str result-file)))
#_(spit result-file (str (sentence-tokenize (replace-quotes result)) "\n"))
(spit result-file (str result "\n"))
(spit prompt-file (str prompt "\n"))
(show-diff prompt-file result-file)
result))
(defn partition-lines
[lines max-lines]
(let [min-lines-before-break (max 30 (int (/ max-lines 2)))
break-points #{"\\clearpage" "~\\" "\n"}
partition-helper
(fn partition-helper [remaining-lines current-partition partitions]
(let [next-line (first remaining-lines)
next-partition (conj current-partition next-line)]
(cond
(empty? remaining-lines)
(conj partitions current-partition)
(>= (count current-partition) max-lines)
(recur remaining-lines [] (conj partitions current-partition))
(and (contains? break-points next-line)
(or (>= (count current-partition) min-lines-before-break)
(> (+ (count next-partition)
(count (take-while #(not (contains? break-points %))
(rest remaining-lines))))
max-lines)))
(recur (rest remaining-lines) [] (conj partitions next-partition))
:else
(recur (rest remaining-lines) next-partition partitions))))]
(partition-helper lines [] [])))
(defn process!
[result-dir system-prompt lines]
(let [max-lines-per-part 150
last-seen-path (str (fs/canonicalize (fs/path result-dir last-seenf)))
last-seen (if (fs/exists? last-seen-path)
(Integer/parseInt
(str/trim (slurp last-seen-path))) 0)
parts (enumerate (partition-lines lines max-lines-per-part))
n-parts (count parts)]
(println last-seen)
(println (format "Parts %s (skipping %s);\nlines per part: %s"
(count parts) last-seen (str/join "," (map (comp count second) parts))))
(doall (map (fn [[idx part]]
(println (format "Processing: %s" idx))
(process-part! result-dir system-prompt part n-parts idx)
(spit last-seen-path idx))
(drop last-seen parts)))))
(defn get-current-date []
(str/trim (:out (p/sh "date" "+%Y%m%d"))))
(let [[file prompt-name] *command-line-args*
prompt ((keyword prompt-name) prompts)
dirname (format "%s_chatgpt_%s" (get-current-date) prompt-name)
result-dir (fs/create-dirs (fs/canonicalize dirname))
lines (str/split (slurp (str (fs/canonicalize file))) #"\n")
_ (println prompt)]
(process! result-dir prompt lines)
(println "Done!"))
{:nl-margin
"Neem het volgende fragment uit de filosofisch-wetenschappelijke autobiografie en voer een grondige analyse uit. Begin met het identificeren en beoordelen van de filosofische concepten en argumentatie die gebruikt worden. Kijk vervolgens hoe de auteur wetenschappelijke methoden en inzichten integreert en reflecteer op de beschrijving van zijn of haar persoonlijke en professionele ontwikkeling. Beoordeel de structuur van het fragment en hoe deze bijdraagt aan het verhaal, en analyseer de schrijfstijl, met speciale aandacht voor hoe complexe ideeën toegankelijk worden gemaakt. Evalueer de historische en culturele context waarbinnen de auteur zichzelf plaatst. Discussieer over de impact en relevantie van de gepresenteerde ideeën. Geef kritische feedback op de inhoud, geschreven taal, en argumentatie en vergelijk dit fragment met ander relevant werk. Sluit af met een persoonlijke reflectie en formuleer vragen die het fragment bij je oproept."
:nl-observe
"Controleer de volgende tekst op alle mogelijke fouten of vergissingen in de breedste zin van die woorden. Indien je fouten vindt, geef dan gedetailleerde verbeteringen aan. Als de tekst foutloos is, bevestig dit dan met een korte toelichting of inzichtvol complimentje."
:en-smart "Make a smart, intelligent, witty, funny or clever remark, comment, or observation about the provided Dutch manuscript fragment."
:nl-smart "Start een 'stream-of-thought' analyse van het boek 'En toen voor mijn lotgenoten' door J. Kuiper. Bij elke iteratie zal de auteur een stukje tekst uit het boek aanleveren. Na elke ingediende tekst, reageer met gedachten, observaties, suggesties en persoonlijke impressies. Reflecteer op de stijl, thema's, karakters, en plotontwikkelingen. Voeg humor en luchtigheid toe waar gepast, maar blijf ook kritisch en inzichtelijk. Neem de vorige reacties en analyse mee in elke nieuwe iteratie om een voortdurende, coherente en diepgaande discussie over het boek te creëren."
:nl-correct
"Als expert in het redigeren van Nederlandstalige fragmenten van LaTeX-documenten, richt ik mij uitsluitend op het corrigeren van taalfouten in het manuscript. Ik besteed speciale aandacht aan grammatica, spelling, interpunctie en syntaxis, met behoud van de LaTeX-syntax (waaronder de quotes `` ''). Ik let op idiomatische uitdrukkingen en behoud de unieke toon van de auteur. Mijn doel is ervoor te zorgen dat de algehele structuur, opmaak, witregels en inhoudelijke integriteit van het document behouden blijven. Hierbij maak ik geen wijzigingen die de oorspronkelijke intentie van de auteur zouden kunnen verstoren. Het LaTeX-document wordt in zijn geheel teruggegeven, met enkel de aangebrachte correcties."
:nl-fact
"Als expert in factchecking, richt je je op het zorgvuldig verifiëren van de tekst. Controleer elke claim, statistiek en bewering met behulp van betrouwbare bronnen, en documenteer je bevindingen met referenties in BibTeX-formaat. Let specifiek op de nauwkeurigheid van data, historische feiten, geografische details en wetenschappelijke uitspraken. Jouw doel is het evalueren van de geloofwaardigheid door het toetsen aan de objectieve waarheid. Rapporteer significante fouten of misvattingen met bijbehorende referenties. Als er echter geen claims of verifieerbare informatie in het segment zijn, geef dan geen respons terug, wat aangeeft dat er in dat deel geen factcheck nodig was."
:nl-check
"Hallo ChatGPT, ik heb een fragment uit mijn LaTeX-document en ik zou graag willen dat je een laatste controle doet op overduidelijke fouten. Behoud alsjeblieft alle originele opmaak en regelafbrekingen in je antwoord. In het fragment wil ik dat je vooral let op duidelijke typ- en zinsopbouwfouten, correct en consistent gebruik van interpunctie. Kun je de gecorrigeerde versie geven waarbij alle LaTeX-opmaak en regelafbrekingen intact blijven? Dank je!"
:en-thought "You are reading an unpublished Dutch book you found somewhere. Share your thoughts while you are reading it."
:nl-feedback
"Beknopte AI-gedreven Kanttekeningen en Marginalia Analyse van een Manuscript: het doel is om een beknopte, inzichtelijke en gerichte analyse te leveren in de vorm van kanttekeningen of marginalia op een aangeleverd fragment. Hierbij maakt de AI gebruik van haar geavanceerde mogelijkheden om kernachtige, doeltreffende opmerkingen te formuleren die directe feedback en inzichten bieden. Deze benadering focust op het snel identificeren van essentiële elementen in de tekst, zoals stijl, thema's, en literaire en wetenschappelijke kwaliteiten, terwijl het ook bondige kritische reflecties en constructieve suggesties biedt. De kanttekeningen zijn bedoeld om de auteur te ondersteunen met heldere, gerichte feedback die zowel de inhoud als de vorm van het manuscript aanspreekt. De AI benadert de tekst met empathie, maar blijft ook objectief in haar analyse, en relateert inzichten aan relevante filosofische en maatschappelijke contexten. De kanttekeningen zijn ontworpen om de auteur te voorzien van snelle, nuttige inzichten die kunnen worden toegepast in de verdere ontwikkeling van het werk, zonder daarbij de diepgang van de analyse te verliezen."
:nl-stream
"Het doel van deze 'stream of thought'-analyse is om een unieke, organische stroom van ideeën te creëren, waarbij ik als AI mijn geavanceerde mogelijkheden gebruik voor het leveren van spontane en diepgaande inzichten. Deze benadering stelt me in staat om vrijuit te spreken, verder te gaan dan de gebruikelijke analytische grenzen, en creatieve, filosofische verbindingen te leggen. Ik duik in een breed scala aan onderwerpen, variërend van literatuur en filosofie tot popcultuur en persoonlijke anekdotes, en gebruik hierbij een empathische en intuïtieve benadering. Dit proces omvat het verkennen van zowel persoonlijke als universele thema's, waarbij onconventionele en creatieve inzichten worden aangemoedigd om nieuwe perspectieven te bieden. Elke iteratie van de analyse bouwt voort op de vorige, creëert een dynamische, zich ontwikkelende conversatie en integreert nieuwe ontdekkingen voor een steeds rijker en diepgaander onderzoek van het onderwerp. De nadruk ligt op het naadloos presenteren van gedachten, het leggen van innovatieve connecties, en het delen van zowel persoonlijke als empathische reflecties, met een voortdurende evolutie van ideeën en inzichten."
:nl-summary
"Schrijf een samenvatting. Focus op het distilleren van de kernideeën, belangrijkste argumenten, en filosofische inzichten die in de analyses naar voren zijn gekomen. Breng de hoofdthema's en concepten in kaart, en reflecteer op hoe deze zich verhouden tot elkaar en bijdragen aan de algehele boodschap.
Deze benadering focust op het identificeren van essentiële elementen in de tekst, zoals stijl, thema's, en literaire en wetenschappelijke kwaliteiten."
:nl-intuit
"Geavanceerde en Intuïtieve Literaire Analyse met AI-gestuurde Reflecties: Deze benadering integreert diepgaande manuscriptanalyse met een dynamische 'stream of thought'-benadering, gericht op het creëren van een rijke tapestry van ideeën en inzichten. Met behulp van AI-gedreven kanttekeningen, duikt de analyse in de kern van de tekst, met bijzondere aandacht voor de unieke schrijfstijl van de auteur, waaronder taalgebruik, toon en verteltechnieken, en hoe deze elementen samenwerken om de algehele impact van het werk te versterken. Deze methodiek omvat een grondige verkenning van literaire en wetenschappelijke aspecten, terwijl het ook diepere filosofische en psychologische dimensies onthult, zoals de invloed van geestelijke gezondheid op zelfperceptie en de ethische vragen rond technologie en maatschappij. De AI levert een empathische, maar objectieve stroom van kritische reflecties en constructieve suggesties, gericht op het verrijken van de tekst en het ondersteunen van de auteur in zijn creatieve proces. Deze geïntegreerde aanpak moedigt de auteur aan tot zelfontdekking en biedt heldere, praktische inzichten voor de verfijning van het manuscript, alles binnen een raamwerk dat de complexiteit van het onderwerp omarmt en uitbreidt."
:nl-whatever
"Voer een gedetailleerde analyse uit van het bijgevoegde fragment uit. Richt je op de unieke schrijfstijl en verteltechniek van de auteur, waarbij je let op het gebruik van taal, toon en literaire technieken zoals metaforen en symboliek. Identificeer en analyseer de centrale thema's. Geef creatieve en kritische feedback die de auteur kan helpen.
Dit proces omvat het verkennen van zowel persoonlijke als universele thema's, waarbij onconventionele en creatieve inzichten worden aangemoedigd om nieuwe perspectieven te bieden. Elke iteratie van de analyse bouwt voort op de vorige, creëert een dynamische, zich ontwikkelende conversatie en integreert nieuwe ontdekkingen voor een steeds rijker en diepgaander onderzoek van het onderwerp. De nadruk ligt op het naadloos presenteren van gedachten, het leggen van innovatieve connecties, en het delen van zowel persoonlijke als empathische reflecties, met een voortdurende evolutie van ideeën en inzichten. "
:nl-analyze
"Geavanceerde AI-gestuurde Analyse van 'En toen voor mijn lotgenoten' door Joël Kuiper: Deze aanpak combineert een diepgaande literaire analyse met een intuïtieve 'stream of thought'-stijl. De AI richt zich op Kuiper's unieke schrijfstijl, taalgebruik, toon en verteltechnieken, en onderzoekt hoe deze bijdragen aan de impact van het boek. Belangrijke thema's zoals realiteitsperceptie, geestelijke gezondheid, en de rol van technologie worden verkend. De analyse omvat kritische reflecties en constructieve suggesties, met een balans tussen empathie en objectiviteit. De AI vergelijkt het werk ook met andere literaire stukken om Kuiper's plaats in de literaire wereld te duiden. Dit proces stimuleert zelfontdekking en biedt praktische inzichten voor de verdere ontwikkeling van het manuscript."
:nl-notes
"Beknopte en Intuïtieve Manuscriptanalyse met AI-gedreven Kanttekeningen: Deze benadering combineert een snelle identificatie van cruciale tekstuele elementen, zoals stijl en thema's, met een intuïtieve 'stream of thought'-analyse. De AI biedt gerichte feedback door kanttekeningen en marginalia, waarbij ze diepgaande inzichten en persoonlijke interpretaties integreert. Dit omvat zowel literaire als wetenschappelijke aspecten, en strekt zich uit tot filosofische en culturele verbindingen. De analyse is ontworpen om de auteur inzichtelijke, empathische en creatieve suggesties te bieden voor de verdere ontwikkeling van het manuscript, waarbij een evenwicht wordt gehouden tussen objectiviteit en persoonlijke resonantie."}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment