[NB : GPT-4를 사용한이 리포지어에 대한 후속 조치는 여기에서 찾을 수 있습니다.]
Chatgpt 및 Claude와 같은 대형 언어 모델 (LLM)은 인상적인 프로그래밍 능력을 보여 주었으며 광범위한 언어 및 분류법에서 문제를 해결할 수 있습니다. 이러한 성공에도 불구하고, 일부 회의론은 이러한 모델이 이러한 언어의 기본 구문 및 운영 규칙에 대한 근본적인 인식을 나타내는 정도에 걸쳐 지속됩니다 (훈련 데이터의 패턴의 암기 ).
이 프롬프트 엔지니어링 저장소에서, ChatGPT의 프로그래밍 능력은 임의의 도메인 별 언어 (DSL)를 사용하여 탐색됩니다. DSL은 LLM의 추론 능력을 연구하기위한 매력적인 기질을 나타냅니다. 왜냐하면 훈련 중 1 명이 신규하고 광범위하게 직면하고 암기했을 가능성이 적기 때문입니다. 따라서, 그들은 LLM이 소수의 방식 으로 새로운 프로그래밍 언어의 규칙을 유추 할 수있는 정도를보다 직접적인 테스트 할 수 있습니다.
여기서는 두 가지 이유로 도메인 별 언어 SIL (Symmetry Integration Language)이 선택되었습니다. 첫째, Chatgpt가 훈련 중에 SIL 코드에 노출되었을 가능성은 거의 없다. 왜냐하면 그것은 Symmetry Investments라는 기술이 많은 헤지 펀드에 의해 개발 된 사내 DSL이기 때문이다. 둘째, 프로그래밍 언어로서, 모델이 재현 할 수있는 흥미로운 기능이 있습니다 (예 : 표현력을 강조하지만 Haskell 또는 OCAML과 같은 let 이 부족한 기능적 언어입니다).

코드 프롬프트 예제 후 Chatgpt는 'SIL'으로 알려진 소설의 기능적 DSL로 코드를 작성하려고 시도합니다.
아래는 SIL 코드의 짧은 예제로 구성된 프롬프트 모음으로 기능을 강조합니다. 작업과 함께 Chatgpt를 홍보하고 SIL 코드 샘플을 제공 한 후 (아래 그림 참조; 전체 프롬프트 기록 및 SIL 코드 예제 도이 리포지토리에 있습니다), 나는 SIL에서 여러 주류 프로그래밍 작업을 구현하도록 요청했습니다.
아래 섹션에서 모델이 프롬프트 된 SIL 코드 스크립트 (여기에서 전체 예제 세트를 찾을 수 있음)와 SIL에서 다양한 문제를 구현하려는 시도 중 일부를 보여줍니다.
첫 번째 프롬프트는 일부 메일 서버 기능을 처리하는 스크립트입니다. 따라서, 그것은 내가 chatgpt가 해결하라는 문제의 유형과 크게 다르지만, SIL의 구문, 데이터 구조 및 기능적 측면 중 일부를 보여줍니다 (예 : |> ).
// 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]) 두 번째 예제 코드 프롬프트는 마찬가지로 모델에 대한이 DSL의 일부 기능을 강조하는 것을 목표로하며 iota 및 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)세 번째 코드 샘플은이 DSL의 비정상적인 기능 중 일부를 추가로 보여 주며 Chatgpt가 다음에 자체 구현에서이를 사용할 것이라는 목표를 보여줍니다.
// 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) 첫 번째 연습으로서, 나는 두 데이터 구조의 차이를 비교하고 인쇄하는 것과 같은 기본 기능과 함께 매우 간단한 관계형 데이터베이스를 SIL으로 구현하도록 모델에 요청했습니다 ( // 는 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]"}]정렬 알고리즘 구현은 전형적인 소프트웨어 엔지니어링 인터뷰 질문입니다. 여기에서 나는 Chatgpt에게 SIL에서 Bubblesort (개념적으로 가장 기본적인 정렬 알고리즘)를 구현하도록 요청했다. 아래는 응답입니다.
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)) 이 스크립트는 실제로 Bubblesort의 작업 구현이지만 모델은 SIL의 기능적 측면을 광범위하게 무시합니다. 예를 들어, 재귀 대신 루프 for 사용하는 Bubblesort의 구현.
다음으로 모델에 목록의 중앙값을 계산하기위한 스크립트를 작성하라는 메시지가 표시되었습니다 (아래의 응답 생성). 이것은 아마도 가장 만족스러운 응답 중 하나 일 것입니다. 첫째, 모델을 자극 한 예제 SIL 코드에 포함 된 if/else 문에도 불구 하고이 생성 된 코드의 구문이 올바르지 않습니다. 둘째, Chatgpt는 math 와 Buil-in 함수 sort 모듈의 존재를 환각 (또는 가정)합니다 (합리적인 가정이지만 프롬프트 문제의 복잡성을 크게 줄입니다).
// 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는 다음으로 k -nearest 이웃 알고리즘을 SIL로 구현하라는 메시지가 표시되었습니다. 모델은 첫 번째 시도에서 distances 라는 모듈을 환각/가정하기 때문에 실제로 두 가지 프롬프트의 결과입니다 (아래 생성 된 코드 블록에 설명). 두 번째 시도에서는이 모듈의 존재를 가정하지 않고 알고리즘을 구현하라는 메시지가 표시되었습니다.
Chatgpt의 성능은 혼합되어 있습니다. 첫째, 일부 경우, 그것은 SIL의 기능적 측면을 무시합니다 (예 : 첫 번째 시도에서 for 구현하는 것과 같은 기능적 측면은 무시합니다. 그러나 구현의 다른 부분에서는 SIL이 기능적이며, |> 운영자를 정확하게 map 하고 있음을 이해하고 있습니다. 특히 모델은 예제 코드에서 특징이없는 let 바인딩을 유해하지 않을 수 있습니다.
// 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 ])
}
기능적 언어의 흥미로운 특징 중 하나는 표현력이 뛰어날 수 있다는 것입니다. 여기에서 Chatgpt에게 기본 기능 연산자 map , filter 및 reduce (또는 기능 언어의 맥락에서 fold )를 구현하라는 메시지가 표시되었습니다. 처음 몇 가지 경우,이 모델은 SIL의 기능적 측면을 추적하는 것처럼 보였지만, 프롬프트 될 때보다 기능적인 방식으로 코드를 다시 구현할 수있었습니다.
// 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는 수학 및 프로그래밍 문제의 모음입니다 (LLM에 대한 흥미로운 프롬프트를 만듭니다). 여기에서는 SIL을 사용하여 처음 두 프로젝트 Euler 문제를 해결하라는 ChatGpt에게 프롬프트합니다. 이 시점에서 Chatgpt의 대표는 다소 무시되었습니다. 이들 솔루션 중 어느 것도 SIL의 높은 수준의 기능 또는 Exaxct 구문과 매우 유사하지 않습니다. 이 시점에서 추가 SIL 코드 예제를 제공 한 다음 모델을 다시 획득하여 이러한 문제를 해결하는 것이 흥미로울 수 있습니다.
// 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)
LLM이 몇 가지 샷 방식으로 새로운 프로그래밍 언어의 특징을 추론하고 이해하는 능력을 탐구하는 것은 개방적이고 흥미로운 질문으로 남아 있습니다. 여기서, 이러한 역량은 Sil이라는 새로운 도메인 별 언어 (DSL)의 문제를 해결하기 위해 Chatgpt를 촉구하는 맥락에서 탐구되었습니다. DSL은 LLM에서 추론 대 암송을 탐색하는 데 잠재적으로 유용한 테스트 사례입니다. 이들은 종종 독특한 특징이 있고 훈련 중에 광범위하게 만났을 가능성이 적기 때문입니다 (경우).
전반적으로 성능이 혼합되었습니다. Chatgpt는이 DSL이 기능적 프로그래밍 언어라는 것을 올바르게 이해했으며 (때로는이를 다시 획득해야했지만) 그에 따라 솔루션을 구현했습니다. 그러나 제공된 5 개의 예제 스크립트 에서이 DSL의 구문 규칙을 캡처하지 못했습니다. 다른 DSL 사용, LLM 생성 코드를 평가하기위한보다 공식적인 지표를 개발하거나 모델의 학습 역학을 정량화하는 등의 추가 조사는이 repo의 흥미로운 확장을 만듭니다. 마지막으로, 별도의 ChatGpt 세션에서, 나는이 메타 프롬프트를 제공하여 모델이 자체 SIL 코드를 해석하는 방법을 결정했습니다.

ChatGpt는 도메인 별 언어 SIL에서 코드를 작성하려는 자체 시도를 검토하고 그 기능 중 일부를 설명합니다.
LLM 암기는 훈련 예제 프리젠 테이션 빈도와 모델을 프롬프트하는 데 사용되는 관련 토큰의 수에 의해 촉진된다는 증거가 있습니다. ↩