[NB: Tindak lanjut dari repo ini menggunakan GPT-4 dapat ditemukan di sini.]
Model bahasa besar (LLM) seperti ChatGPT dan Claude telah menunjukkan kemampuan pemrograman yang mengesankan, dan mampu memecahkan masalah di berbagai bahasa dan taksonomi mereka. Terlepas dari keberhasilan ini, beberapa skeptis berlanjut sejauh model -model ini menunjukkan apresiasi yang mendasari aturan sintaksis dan operasional yang mendasari bahasa -bahasa ini ( versus menghafal pola dari data pelatihan).
Dalam repositori rekayasa cepat ini, kemampuan pemrograman chatgpt dieksplorasi menggunakan bahasa khusus domain sewenang-wenang (DSL). DSL mewakili substrat yang menarik untuk mempelajari kemampuan inferensi LLM karena mereka baru dan lebih kecil kemungkinannya untuk ditemui dan dihafal secara luas selama pelatihan 1 . Dengan demikian, mereka memungkinkan tes yang lebih langsung sejauh mana LLM dapat menyimpulkan aturan bahasa pemrograman baru dalam beberapa hal .
Di sini, SIL bahasa khusus domain (bahasa integrasi simetri) dipilih karena dua alasan. Pertama, sangat tidak mungkin bahwa ChatGPT telah terpapar pada kode SIL selama pelatihan, karena ini adalah DSL in-house yang dikembangkan oleh dana lindung nilai teknologi yang disebut Symmetry Investments. Kedua, sebagai bahasa pemrograman, ia memiliki beberapa fitur yang menarik untuk direproduksi oleh model (misalnya itu adalah bahasa fungsional yang menekankan ekspresi, tetapi tidak memiliki ekspresi let seperti di Haskell atau OCAML).

Setelah beberapa contoh kode contoh, chatgpt mencoba untuk menulis kode dalam novel, DSL fungsional yang dikenal sebagai 'SIL'.
Di bawah ini adalah kumpulan petunjuk yang terdiri dari contoh -contoh singkat kode SIL yang menyoroti fungsinya. Setelah meminta chatgpt dengan tugas dan memberikan sampel kode SIL (lihat gambar di bawah ini; sejarah prompt penuh dan contoh kode SIL juga ada dalam repo ini), saya memintanya untuk mengimplementasikan sejumlah tugas pemrograman arus utama di SIL.
Pada bagian di bawah ini, saya menunjukkan beberapa contoh skrip kode SIL yang dengannya model diminta (set lengkap contoh dapat ditemukan di sini) dan upayanya untuk menerapkan berbagai masalah di SIL.
Prompt pertama adalah skrip untuk menangani beberapa fungsionalitas server surat. Dengan demikian, ini sangat berbeda dari jenis masalah yang kemudian saya akan segera minta chatgpt untuk dipecahkan, tetapi itu menggambarkan beberapa sintaks, struktur data, dan aspek fungsional SIL (misalnya |> ).
// 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]) Contoh kode contoh kedua juga bertujuan untuk menyoroti beberapa fitur DSL ini untuk model, dan memperkenalkan beberapa fungsi perpustakaan standar baru seperti iota dan fold .
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)Sampel kode ketiga lebih lanjut menggambarkan beberapa fitur yang tidak biasa dari DSL ini, dengan tujuan bahwa chatgpt akan menggunakannya dalam implementasinya sendiri berikutnya.
// 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) Sebagai latihan pertama, saya meminta model untuk mengimplementasikan database relasional yang sangat sederhana di SIL, dengan fungsi dasar seperti membandingkan dan mencetak perbedaan antara dua struktur data (perhatikan bahwa // menunjukkan komentar di SIL).
// 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]"}]Menerapkan algoritma penyortiran adalah pertanyaan wawancara rekayasa perangkat lunak pola dasar. Di sini, saya meminta ChatGPT untuk mengimplementasikan Bubblesort (secara konseptual algoritma penyortiran paling mendasar) di SIL. Di bawah ini adalah tanggapannya:
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)) Meskipun skrip ini, memang, implementasi kerja Bubblesort, model secara luas mengabaikan aspek fungsional SIL. Misalnya, implementasi Bubblesort ini menggunakan for loop, bukan rekursi.
Selanjutnya, saya meminta model untuk menulis skrip untuk menghitung median daftar (respons yang dihasilkan di bawah). Ini, mungkin, salah satu tanggapan yang paling tidak memuaskan. Pertama, terlepas dari pernyataan if/else yang menampilkan dalam contoh kode SIL yang saya minta model, sintaks dalam kode yang dihasilkan ini salah. Kedua, chatgpt berhalusinat (atau mengasumsikan) keberadaan modul yang disebut math dan sort fungsi buil-in (ini adalah asumsi yang masuk akal, tetapi secara signifikan mengurangi kompleksitas masalah yang diminta).
// 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 berikutnya diminta untuk mengimplementasikan algoritma Nearbors K -Nearest di SIL. Ini sebenarnya adalah hasil dari dua petunjuk (seperti yang dijelaskan dalam blok kode yang dihasilkan di bawah), karena model berhalusinat/mengasumsikan modul yang disebut distances dalam upaya pertama. Dalam upaya kedua, saya meminta untuk mengimplementasikan algoritma tanpa mengasumsikan keberadaan modul ini.
Kinerja ChatGPT di sini beragam. Pertama, dalam beberapa kasus, itu mengabaikan aspek fungsional SIL (seperti menerapkan for untuk upaya pertama. Namun, di bagian lain implementasi, bagaimanapun, ia menghargai let SIL adalah fungsional, dan menggunakan |> dan map operator secara akurat. Khususnya, ini tampaknya.
// 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 ])
}
Salah satu fitur menarik dari bahasa fungsional adalah bahwa mereka bisa sangat ekspresif. Di sini, saya meminta chatgpt untuk mengimplementasikan map operator fungsional dasar, filter , dan reduce (atau fold dalam konteks bahasa fungsional). Untuk beberapa kasus pertama, model tampaknya kehilangan jejak aspek fungsional SIL, tetapi dapat mengimplementasikan kembali kode dengan cara yang lebih fungsional ketika diminta.
// 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 adalah kumpulan masalah matematika dan pemrograman (yang saya pikir membuat permintaan yang menarik untuk LLMS). Di sini, saya meminta chatgpt untuk menyelesaikan dua masalah proyek pertama menggunakan SIL. Pada titik ini, repsons chatgpt agak deriorasi; Tak satu pun dari solusi ini memiliki banyak kemiripan dengan fungsionalitas tingkat tinggi dari SIL maupun sintaksisnya. Mungkin menarik untuk memberikan contoh kode SIL lebih lanjut pada titik ini dan kemudian mempromosikan kembali model untuk menyelesaikan masalah ini.
// 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)
Menjelajahi kemampuan LLMS untuk menyimpulkan dan memahami fitur-fitur bahasa pemrograman baru dalam beberapa hal tetap merupakan pertanyaan yang terbuka dan menarik. Di sini, kapasitas ini dieksplorasi dalam konteks mendorong chatgpt untuk menyelesaikan masalah yang diminta dalam bahasa spesifik domain (DSL) baru yang disebut SIL. DSL adalah kasus uji yang berpotensi berguna untuk mengeksplorasi inferensi vs menghafal di LLMS, karena sering memiliki fitur khas dan cenderung telah ditemui secara luas selama pelatihan (jika sama sekali).
Secara keseluruhan, kinerja beragam: ChatGPT dengan benar dipahami bahwa DSL ini adalah bahasa pemrograman fungsional (meskipun kadang-kadang harus dimasukkan kembali tentang hal ini), dan menerapkan solusinya sesuai. Namun, secara luas gagal menangkap aturan sintaksis DSL ini dari lima contoh skrip yang disediakan. Investigasi lebih lanjut (seperti menggunakan DSL lainnya, mengembangkan beberapa metrik yang lebih formal untuk mengevaluasi kode yang dihasilkan LLM, atau mengukur dinamika pembelajaran model) akan membuat perpanjangan yang menarik dari repo ini. Akhirnya, dalam sesi chatgpt yang terpisah, saya menyediakan meta-prompt ini untuk menentukan bagaimana model menafsirkan kode SIL sendiri:

ChatGPT memeriksa upayanya sendiri untuk menulis kode dalam bahasa khusus domain SIL, dan menggambarkan beberapa fiturnya.
Ada bukti bahwa menghafal LLM dipromosikan oleh frekuensi presentasi contoh pelatihan dan jumlah token yang relevan yang digunakan untuk mendorong model. ↩