2024-07-15 14:52:50 -04:00
|
|
|
/-
|
|
|
|
Copyright (c) 2024 Joseph Tooby-Smith. All rights reserved.
|
|
|
|
Released under Apache 2.0 license.
|
|
|
|
Authors: Joseph Tooby-Smith
|
|
|
|
-/
|
|
|
|
import Batteries.Lean.IO.Process
|
|
|
|
import Lean
|
|
|
|
import Lean.Parser
|
|
|
|
import Lean.Data.Json
|
|
|
|
import Mathlib.Lean.CoreM
|
|
|
|
import LLM.GPT.Json
|
|
|
|
import LLM.GPT.API
|
|
|
|
/-!
|
|
|
|
|
|
|
|
# HepLean OpenAI doc check
|
|
|
|
|
|
|
|
This file uses the openAI API to check the doc strings of definitions and theorems in a
|
|
|
|
Lean 4 file.
|
|
|
|
|
2024-07-15 15:10:10 -04:00
|
|
|
This file depends on `https://github.com/leanprover-community/llm` being imported.
|
|
|
|
This is not currently done by default.
|
2024-07-15 14:52:50 -04:00
|
|
|
|
|
|
|
-/
|
|
|
|
open Lean
|
|
|
|
open LLM
|
|
|
|
open System Meta
|
|
|
|
|
|
|
|
def getDocString (constName : Array ConstantInfo) : MetaM String := do
|
|
|
|
let env ← getEnv
|
|
|
|
let mut docString := ""
|
|
|
|
for c in constName do
|
|
|
|
if ¬ Lean.Name.isInternalDetail c.name then
|
|
|
|
let doc ← Lean.findDocString? env c.name
|
|
|
|
match doc with
|
|
|
|
| some x => docString := docString ++ "- " ++ x ++ "\n"
|
|
|
|
| none => docString := docString
|
|
|
|
return docString
|
|
|
|
|
|
|
|
def header : String := "
|
|
|
|
Answer as if you an expert mathematician, physicist and software engineer.
|
|
|
|
Below I have listed the doc strings of definitions and theorems in a Lean 4 file.
|
|
|
|
Output a list of 1) spelling mistakes. 2) grammatical errors. 3) suggestions for improvement.
|
|
|
|
Note that text within `...` should be treated as code and not spellchecked. Doc strings
|
|
|
|
should be a complete sentence, or a noun phrase.
|
|
|
|
|
|
|
|
|
|
|
|
"
|
|
|
|
|
|
|
|
def main (args : List String) : IO UInt32 := do
|
|
|
|
initSearchPath (← findSysroot)
|
|
|
|
let firstArg := args.head?
|
|
|
|
match firstArg with
|
|
|
|
| some x => do
|
|
|
|
let mut imp : Import := Import.mk x.toName false
|
|
|
|
if x == "random" then
|
|
|
|
let mods : Name := `HepLean
|
|
|
|
let imps : Import := {module := mods}
|
|
|
|
let mFile ← findOLean imps.module
|
|
|
|
unless (← mFile.pathExists) do
|
|
|
|
throw <| IO.userError s!"object file '{mFile}' of module {imps.module} does not exist"
|
|
|
|
let (hepLeanMod, _) ← readModuleData mFile
|
|
|
|
let imports := hepLeanMod.imports
|
|
|
|
let y ← IO.rand 0 (imports.size -1)
|
|
|
|
imp := imports.get! y
|
|
|
|
let mFile ← findOLean imp.module
|
|
|
|
let filePath := (mkFilePath (imp.module.toString.split (· == '.'))).addExtension "lean"
|
|
|
|
IO.println s!"Checking: {filePath}"
|
|
|
|
let (modData, _) ← readModuleData mFile
|
|
|
|
let cons := modData.constants
|
|
|
|
let docString ← CoreM.withImportModules #[imp.module] (getDocString cons).run'
|
|
|
|
let message : LLM.Message := {role := Role.user, content := header ++ docString}
|
|
|
|
let request : GPT.Request := {messages := [message]}
|
|
|
|
let response ← LLM.GPT.chat (toString <| ToJson.toJson request)
|
|
|
|
let parsedRespone := GPT.parse response
|
|
|
|
match parsedRespone with
|
|
|
|
| .ok x => IO.println x
|
|
|
|
| .error e => IO.println e
|
|
|
|
| none => IO.println "No module provided."
|
|
|
|
return 0
|