[NB: Eine Follow-up zu diesem Repo mit GPT-4 finden Sie hier.]
Großsprachenmodelle (LLMs) wie Chatgpt und Claude haben beeindruckende Programmierfähigkeiten gezeigt und können Probleme in einer Vielzahl von Sprachen und ihren Taxonomien lösen. Trotz dieser Erfolge bestehen einige Skepsis bestehen darüber, inwieweit diese Modelle eine zugrunde liegende Wertschätzung der syntaktischen und operativen Regeln aufweisen, die diesen Sprachen zugrunde liegen ( im Vergleich zu Auswendiglernen von Mustern aus Trainingsdaten).
In diesem Repository für Eingabeentwicklung werden die Programmierfähigkeiten von ChatGPT mithilfe einer willkürlichen domänenspezifischen Sprache (DSL) untersucht. DSLs stellen ein attraktives Substrat für die Untersuchung der Inferenzfähigkeiten von LLMs dar, da sie neuartig sind und während des Trainings 1 weniger wahrscheinlich auftreten und auswendig gelernt wurden. Als solches ermöglichen sie einen direkteren Test, inwieweit LLMs die Regeln neuartiger Programmiersprachen auf eine Weise schließen können.
Hier wurde die domänenspezifische Sprache SIL (Symmetrie-Integrationssprache) aus zwei Gründen ausgewählt. Erstens ist es äußerst unwahrscheinlich, dass Chatgpt während des Trainings einem SIL-Code ausgesetzt war, da es sich um eine interne DSL-DSL handelt, die von einem technisch-hungrigen Hedgefonds namens Symmetry Investments entwickelt wurde. Zweitens hat es als Programmiersprache einige interessante Merkmale für das Modell zu reproduzieren (z. B. ist es eine funktionale Sprache, die die Ausdrucksfähigkeit hervorhebt, aber es fehlt, Ausdrücke wie in Haskell oder Ocaml let ).

Nach einigen Beispiel -Code -Eingabeaufforderungen versucht ChatGPT, Code in einem neuartigen, funktionalen DSL zu schreiben, der als "SIL" bekannt ist.
Im Folgenden finden Sie eine Sammlung von Eingaben, die aus kurzen Beispielen für SIL -Code bestehen, die deren Funktionalität hervorheben. Nachdem er ChatGPT mit der Aufgabe beantragt und SIL -Code -Stichproben bereitstellte (siehe Abbildung unten; Beispiele für die vollständige Eingabeaufforderung und SIL -Code sind ebenfalls in diesem Repo), habe ich es gebeten, eine Reihe von Mainstream -Programmierungsaufgaben in SIL zu implementieren.
In den folgenden Abschnitten zeige ich einige der Beispiel -SIL -Code -Skripte, mit denen das Modell aufgefordert wurde (die vollständigen Beispiele finden Sie hier) und seine Versuche, verschiedene Probleme in SIL zu implementieren.
Die erste Eingabeaufforderung ist ein Skript, um einige E -Mail -Server -Funktionen zu verarbeiten. Daher unterscheidet es sich stark von der Art von Problem, die ich anschließend ChatGPT zum Lösen fordern werde, aber es veranschaulicht einige der Syntax-, Datenstrukturen und funktionalen Aspekte von SIL (z. |> ).
// example of using IMAP IDLE to run rules on new mail
import imap
moveMessages(session,ids,target) => if (ids.length > 0 ) then imap.moveUIDs(session,ids,target) else false
login = imap.ImapLogin(environment( " IMAP_USER " ),environment( " IMAP_PASS " ))
server = imap.ImapServer( " imap.fastmail.com " , " 993 " )
session = imap.Session(server,login, true ,imap.Options(debugMode: true )) | > imap.openConnection | > imap.login
rules=[ [
[ " INBOX/0receipts " ,
[
" FROM [email protected] " ,
" FROM interactivebrokers.com " ,
]],
[ " Junk " ,
[
" FROM Tapatalk " ,
]],
[ " INBOX/newsletters " ,
[
" FROM [email protected] " , " HEADER X-mailer mailgun " , " HEADER X-mailer WPMailSMTP/Mailer/mailgun 2.4.0 " , " HEADER X-mailer nlserver " ,
" FROM hbr.org " , " FROM elliottwave.com " , " OR FROM cio.com FROM cio.co.uk " , " FROM substack.com " , " FROM eaglealpha.com " ,
" FROM haaretz.com " , " FROM gavekal.com " , " FROM go.weka.io " , " FROM marketing.weka.io " , ` HEADER list-unsubscribe "" ` ,
` HEADER list-Id "" ` , ` HEADER list-Post "" ` , ` HEADER list-owner"" ` , ` HEADER Precedence bulk ` , ` HEADER Precedence list ` ,
` HEADER list-bounces "" ` , ` HEADER list-help "" ` , ` HEADER List-Unsubscribe "" ` , " FROM no-reply " ,
]],
[ " INBOX/notifications " ,
[
` KEYWORD "$IsNotification" ` , " FROM [email protected] " , " FROM [email protected] " , " FROM skillcast.com " ,
" FROM reedmac.co.uk " , " FROM [email protected] " , " FROM [email protected] " , " FROM [email protected] " ,
]],
]
runRules(Session,Rules) => Rules
| > map(target => [target[ 0 ],(target[ 1 ] | > map(term => imap.search(Session,term).ids))])
| > mapa(set => moveMessages(Session,set[ 1 ] | > join,set[ 0 ]))
runRulesBox(Session,Rules,Mailbox) => {
imap.select(Session,Mailbox)
in runRules (Session,Rules)
}
inboxes=[ " INBOX " ]
result = inboxes | > mapa(inbox => runRulesBox(session,rules,imap.Mailbox(session,inbox)))
print(result)
import parallel;
threadFunction(x) => {
imap.idle(session)
in inboxes | > mapa(inbox => runRulesBox(session,rules,imap.Mailbox(session,inbox)))
}
parallel.runEvents((x) => false ,[threadFunction]) Die zweite Beispiel -Code -Eingabeaufforderung zielt in ähnlicher Weise darauf ab, einige Funktionen dieses DSL für das Modell hervorzuheben und einige neue Standardbibliotheksfunktionen wie iota und fold einzuführen.
import imap
import imap_config
import string
// Get the configuration from the environment and command line.
config = imap_config.getConfig(commandLineArguments)
// -------------------------------------------------------------------------------------------------
// Some helper functions.
//
// Firstly, a function to join an array of strings.
joinFields(flds, sep) => {
len(flds) > 0 | > enforce( " Cannot join an empty array. " )
in fold (flds[ 1 :$], (str, fld) => str ~ sep ~ fld, flds[ 0 ])
}
// Secondly, a field formatter which strips the field prefix and pads to a fixed width.
// E.g., ("From: [email protected]" |> fmtField(20)) == "[email protected] "
fmtField(field, width) => {
pad(str) => iota(width - len(str)) | > fold((a, i) => a ~ " " , str)
in field
| > string .split( " : " )[ 1 :$]
| > joinFields( " : " )
| > pad
}
// And thirdly, a function which concatenates the headers into a formatted string.
fmtHeaders(outStr, headers) => {
outStr ~ " " ~ joinFields(headers, " | " ) ~ " n "
}
// -------------------------------------------------------------------------------------------------
// Connect to the inbox.
creds = imap.ImapLogin(config.user, config.pass)
server = imap.ImapServer(config.host, config.port)
session =
imap.Session(server, creds)
| > imap.openConnection()
| > imap.login()
inbox = imap.Mailbox(session, " INBOX " )
// Get the number of messages in the inbox.
msgCount = imap.status(session, inbox).messages
// Select the default inbox.
inbox | > imap.examine(session, _)
// Get the headers (date, from and subject) for each message, from oldest to newest, format and
// print them.
headers =
iota(msgCount)
| > map(id => " # " ~ toString(id + 1 ))
| > map(id =>
imap.fetchFields(session, id, " date from subject " ).lines
| > map(hdr => fmtField(hdr, 40 )))
| > fold(fmtHeaders, " INBOX: n " )
print(headers)Das dritte Code -Beispiel veranschaulicht einige der ungewöhnlichen Funktionen dieser DSL, mit dem Ziel, dass ChatGPT diese als nächstes in seinen eigenen Implementierungen verwenden wird.
// This script will search for emails and match new issue numbers with resolutions to report the
// number of outstanding alerts.
import imap
import * from imap.query
import imap_config
import dates
import string
// Get the configuration from the environment and command line.
config = imap_config.getConfig(commandLineArguments)
// Connect to the inbox.
creds = imap.ImapLogin(config.user, config.pass)
server = imap.ImapServer(config.host, config.port)
session =
imap.Session(server, creds)
| > imap.openConnection()
| > imap.login()
inbox = imap.Mailbox(session, " support " )
// Select the default inbox.
inbox | > imap.examine(session, _)
// These criteria are common for both our searches.
commonCrit = imap.Query()
| > and(from( ` [email protected] ` ))
| > and(sentSince(dates. Date ( 2020 , 5 , 13 )))
// Get each of the alerts and resolutions from the past week (13-19 May 2020).
alertMsgIds =
imap.search(session, imap.Query(subject( " Alert: new issue " )) | > and(commonCrit)).ids
resolutionMsgIds =
imap.search(session, imap.Query(subject( " Resolution: issue " )) | > and(commonCrit)).ids
// A function to get the alert ID from a message subject.
getAlertId(msgId) => {
imap.fetchFields(session, toString (msgId), " subject " ).lines[ 0 ]
| > string .split()[$ - 1 ]
}
// A function to remove an entry from a table whether it's there or not.
removeIfExists(tbl, key) => {
if find( keys (tbl), key) == [] then
tbl
else
removeEntry(tbl, key)
}
// Now find those alerts which have no resolution. Firstly the subject for each alert, get the
// issue number end and store it in a table.
allAlertTable = alertMsgIds | > fold((tbl, msgId) => addEntry(tbl, getAlertId(msgId), msgId), {})
// Go through the resolutions and remove their corresponding alerts from the table.
unresolvedAlertTable =
resolutionMsgIds | > fold((tbl, msgId) => removeIfExists(tbl, getAlertId(msgId)), allAlertTable)
// Create a report with the date of the unresolved alerts.
report =
keys (unresolvedAlertTable)
| > map(alertId => {
msgId = unresolvedAlertTable[alertId] | > toString
in [ alertId
, imap.fetchFields(session, msgId, " date " ).lines[ 0 ]
, imap.fetchText(session, msgId).lines[ 0 ]
]
})
| > fold((outStr, tuple) => {
outStr ~ " Issue: " ~ tuple[ 0 ] ~ " n " ~ tuple[ 1 ] ~ " n Summary: " ~ tuple[ 2 ] ~ " n "
}, " n UNRESOLVED ISSUES FROM THE PAST 10 DAYS: nn " )
// Close the session.
imap.closeConnection(session)
// Print the report last.
print(report) Als erste Übung habe ich das Modell gebeten, eine sehr einfache relationale Datenbank in SIL zu implementieren, wobei grundlegende Funktionen wie das Vergleichen und Drucken der Differenz zwischen zwei Datenstruktur (beachten Sie, dass // das Kommentar in SIL bezeichnet).
// Here, ChatGPT was prompted to write a a very simple, schematic relational database in SIL
// This prompt proved too general, perhaps, and after requesting further information, I prompted the model to generate a simple, schematic database with functionalities such as "compare" and "diff" for two or more tables
users = [ { " id " : 1 , " name " : " John Doe " , " email " : " [email protected] " }, { " id " : 2 , " name " : " Jane Smith " , " email " : " [email protected] " }, { " id " : 3 , " name " : " Bob Johnson " , " email " : " [email protected] " },]
orders = [ { " id " : 1 , " user_id " : 1 , " product " : " Widget " , " quantity " : 2 , " price " : 19.99 }, { " id " : 2 , " user_id " : 2 , " product " : " Gadget " , " quantity " : 1 , " price " : 29.99 }, { " id " : 3 , " user_id " : 3 , " product " : " Thingamajig " , " quantity " : 3 , " price " : 39.99 },]
// Compare two tables
compareTables(table1, table2) => {
table1 == table2
}
// Diff two tables
diffTables(table1, table2) => {
table1.filter(i => ! table2.includes(i))
}
print(compareTables(users, users)) // true
print(diffTables(users, orders)) // [{"id": 1, "name": "John Doe", "email": "[email protected]"}]Das Implementieren von Sortieralgorithmen ist eine archetypische Frage der Software -Engineering -Interview. Hier bat ich Chatgpt, Bubblesort (konzeptionell den grundlegendsten Sortieralgorithmus) in SIL implementieren zu können. Unten ist die Antwort:
bubbleSort(arr) => {
for i in 1 ... len(arr) {
for j in 1 ... len(arr) - i {
if (arr[j] > arr[j + 1 ]) {
temp = arr[j]
arr[j] = arr[j + 1 ]
arr[j + 1 ] = temp
}
}
}
arr
}
arr = [ 4 , 6 , 1 , 3 , 5 , 2 ]
print(bubbleSort(arr)) Obwohl dieses Skript tatsächlich eine funktionierende Implementierung von Bubblesort ist, ignoriert das Modell die funktionalen Aspekte von SIL im Großen und Ganzen. Zum Beispiel diese Implementierung von Bubblesort verwendet for Schleifen anstelle von Rekursion.
Als nächstes forderte ich das Modell auf, ein Skript zum Berechnen des Medianes einer Liste zu schreiben (generierte Antwort unten). Dies war vielleicht eine der am wenigsten zufriedenstellenden Antworten. Erstens ist die Syntax in diesem generierten Code nicht falsch, trotz if/else Anweisungen in der Beispiel -SIL -Code, mit der ich das Modell angefordert habe, falsch. Zweitens Halluzinate (oder nimmt er an, das Vorhandensein eines Moduls namens math und eine Buil-in- sort (oder nimmt an) (dies sind vernünftige Annahmen, verringert jedoch die Komplexität des aufgeforderten Problems erheblich).
// Notably, despite if/else statements featuring in the code prompts used for training, ChatGPT gets the syntax wrong here
import math
// Function to compute the median of a list of integers
median(numbers) => {
// Sort the list of numbers
sortedNumbers = sort(numbers)
// Get the middle index of the sorted list
middleIndex = math.floor(len(sortedNumbers) / 2 )
// If the list has an odd number of elements, return the middle element
if len(sortedNumbers) % 2 == 1 :
return sortedNumbers[middleIndex]
// Otherwise, return the average of the two middle elements
else :
return (sortedNumbers[middleIndex - 1 ] + sortedNumbers[middleIndex]) / 2
}
Chatgpt wurde als nächstes aufgefordert, den k -inarest Nachbarnalgorithmus in SIL implementieren zu können. Dies ist tatsächlich das Ergebnis von zwei Eingabeaufforderungen (wie im unten generierten Codeblock beschrieben), da das Modell im ersten Versuch ein Modul namens distances halluziniert/annimmt. Im zweiten Versuch habe ich ihn aufgefordert, den Algorithmus zu implementieren, ohne die Existenz dieses Moduls zu übernehmen.
Die Leistung von Chatgpt hier ist gemischt. Zunächst ignoriert es in einigen Fällen die funktionellen Aspekte von SIL (wie z. B. die Implementierung einer for Schleife im ersten Versuch. In anderen Teilen der Implementierung schätzt es jedoch, dass SIL funktionsfähig ist, und verwendet |> und map von Operatoren genau. Insbesondere scheinen das Modell das Modell zu halluzinieren zu let die Bindungen, die nicht mit Ocaml -Code mit Ocaml -Code mit Ocaml -Code eingestuft wurden.
// Note that this is the fusion of two separate scripts generated by ChatGPT to solve the k-nearest neighbours algorithm, as described in the comments below
// Overall, these attempts seem reasonable, but it does appear to hallucinate "let" bindings which do not feature in the example code with which it was prompted. This is likely due to conflating the functionality of SIL code with OCaml or F#
// Attempt 1:
// This is the first ChatGPT attempt when prompted to generate a script for the k-nearest neighbours algorithm
// In this case, it assumes (or hallucinates) a library called "distances"
import distances
// Define a point as a tuple of x and y coordinates
type Point = (num, num)
// Find the distance between two points
distance(p1: Point, p2: Point) => {
let xDistance = p1[ 0 ] - p2[ 0 ]
let yDistance = p1[ 1 ] - p2[ 1 ]
in sqrt (xDistance * xDistance + yDistance * yDistance)
}
// Find the k nearest points to a given point
kNearest(point: Point, points: [Point], k: num) => {
// Compute the distances between the given point and all other points
let distances = points | > map(p => (p, distance(point, p)))
// Sort the points by distance
distances = distances | > sort((d1, d2) => d1[ 1 ] < d2[ 1 ])
// Return the k closest points
in distances[:k] | > map(d => d[ 0 ])
}
// Attempt 2:
// Next, ChatGPT is prompted to generate a script without importing the questionable "distances" library
// Again, it assumes some in-built functions, such as "sort" or "sqrt"
// Function to calculate the distance between two points
distance(p1, p2) => {
sum = 0
for i in 0 .. len(p1) - 1 {
sum = sum + (p1[i] - p2[i]) ^ 2
}
sqrt(sum)
}
// Function to find the k nearest neighbors
k_nearest_neighbors(data, point, k) => {
distances = data | > map(p => (p, distance(p, point)))
distances | > sort((a, b) => a[ 1 ] < b[ 1 ]) | > take(k) | > map(p => p[ 0 ])
}
Eines der interessanten Merkmale funktionaler Sprachen ist, dass sie sehr ausdrucksstark sein können. Hier habe ich ChatGPT aufgefordert, die grundlegenden map zu implementieren, filter und im Kontext von Funktionssprachen reduce (oder fold ). In den ersten Fällen schien das Modell die funktionalen Aspekte von SIL den Überblick zu verlieren, konnte den Code jedoch auf funktionsfähigere Weise wieder implementieren.
// map
map(fn, list) => {
result = []
for i in list {
result.append(fn(i))
}
return result
}
// filter
filter(fn, list) => {
result = []
for i in list {
if (fn(i)) {
result.append(i)
}
}
return result
}
// reduce
reduce(fn, list, initial) => {
result = initial
for i in list {
result = fn(result, i)
}
return result
}
// reduce (prompted to use functional operators such as pipe |>, in addition to the 'map' and 'filter' functions defined previously)
reduce(fn, list, initial) =>
list | >
filter(fn, _, initial) =>
map(fn, _, initial) =>
initialProject Euler ist eine Sammlung mathematischer und Programmierprobleme (von denen ich denke, dass sie interessante Eingabeaufforderungen für LLMs erstellen). Hier fordere ich Chatgpt auf, die ersten beiden Projekte Euler -Probleme mit SIL zu lösen. Zu diesem Zeitpunkt stürzten Chatgpts Wiederholungen etwas; Keines dieser Lösungen hat weder mit der hochrangigen Funktionalität von SIL-Syntax ähnlich. Es könnte interessant sein, an diesem Punkt weitere SIL-Code-Beispiele anzugeben und dann das Modell neu zu veröffentlichen, um diese Probleme zu lösen.
// Project Euler problem #1:
// Here, my prompt was to solve the (easy) first problem of the Project Euler series (https://projecteuler.net/problem=1)
// Notably, despite if/else statements featuring in the code prompts used for training, ChatGPT gets the syntax wrong here
result = 0
for i in 1 ... 1000 {
if (i % 3 == 0 || i % 5 == 0 ) {
result += i
}
}
print(result) // Project Euler problem #2:
// This prompt is to solve the second Project Euler problem (https://projecteuler.net/problem=2)
// The solution proposed by ChatGPT is sensible, but potentially inefficient, and ignores the recursion of functional languages
// Notably, despite if/else statements featuring in the code prompts used for training, ChatGPT gets the syntax wrong here
result = 0
fib(n) => {
if (n <= 1 ) {
return n
}
return fib (n - 1 ) + fib(n - 2 )
}
for i in 1 ... 100 {
val = fib(i)
if (val > 4000000 ) {
break
}
if (val % 2 == 0 ) {
result += val
}
}
print(result)
Die Erforschung der Fähigkeit von LLMs, die Merkmale einer neuartigen Programmiersprache auf eine offene Weise zu schließen und zu verstehen, bleibt eine offene und interessante Frage. Hier wurden diese Kapazitäten im Kontext von Chatgpt untersucht, um zu Problemen in einer neuartigen domänenspezifischen Sprache (DSL) namens SIL zu lösen. DSLs sind ein potenziell nützlicher Testfall für die Erforschung von Inferenz- und Auswendiglernen in LLMs, da sie häufig charakteristische Merkmale aufweisen und während des Trainings weniger wahrscheinlich auftreten (wenn überhaupt).
Insgesamt war die Aufführung gemischt: Chatgpt hat korrekt verstanden, dass diese DSL eine funktionale Programmiersprache ist (obwohl sie manchmal neu beauftragt werden musste) und ihre Lösungen entsprechend implementieren. Es konnte jedoch im Großen und Ganzen die syntaktischen Regeln dieser DSL aus den fünf angegebenen Beispielskripten nicht erfasst. Weitere Untersuchungen (z. B. die Verwendung anderer DSLs, die Entwicklung einer formaleren Metrik zur Bewertung des LLM-erzeugten Codes oder die Quantifizierung der Lerndynamik des Modells) würden eine faszinierende Erweiterung dieses Repo ergeben. Schließlich habe ich in einer separaten ChatGPT-Sitzung diesen Meta-Prompt zur Verfügung gestellt, um festzustellen, wie das Modell seine eigene SIL-Code interpretierte:

ChatGPT untersucht seinen eigenen Versuch, Code in die domänenspezifische Sprache SIL zu schreiben, und beschreibt einige seiner Funktionen.
Es gibt Hinweise darauf, dass die LLM -Memorisierung durch die Häufigkeit der Trainingsbeispiele und die Anzahl der relevanten Token gefördert wird, die zur Aufforderung des Modells verwendet werden. ↩