[NB:GPT-4を使用したこのレポのフォローアップは、こちらにあります。]
ChatGptやClaudeなどの大規模な言語モデル(LLM)は、印象的なプログラミング能力を実証しており、幅広い言語とその分類法で問題を解決することができます。これらの成功にもかかわらず、これらのモデルがこれらの言語の根底にある構文および運用ルールの根本的な評価を示す程度には、いくつかの懐疑論が持続します(トレーニングデータからのパターンの記憶に対して)。
このプロンプトエンジニアリングリポジトリでは、ChATGPTのプログラミング能力が任意のドメイン固有の言語(DSL)を使用して検討されます。 DSLは、LLMSの推論機能を研究するための魅力的な基質を表しており、トレーニング中に広く遭遇し、記憶された可能性が低いためです。そのため、LLMSが新しいプログラミング言語のルールをいくつかのショット方法で推測できる範囲のより直接的なテストを可能にします。
ここでは、2つの理由でドメイン固有の言語SIL(対称統合言語)が選択されました。第一に、対称投資と呼ばれるハイテクヘビーヘッジファンドによって開発された社内DSLであるため、CHATGPTがトレーニング中にあらゆるSILコードにさらされる可能性は非常に低いです。第二に、プログラミング言語として、モデルが再現するための興味深い機能がいくつかあります(たとえば、表現力を強調する機能的な言語ですが、HaskellやOCAMLのように表現let欠いています)。

いくつかの例コードプロンプトの後、ChatGPTは「SIL」として知られる斬新な機能的DSLでコードを書き込もうとします。
以下は、その機能を強調するSILコードの短い例で構成されるプロンプトのコレクションです。 The 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]) 2番目の例コードプロンプトも同様に、モデルのこの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)3番目のコードサンプルは、この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で非常に単純なリレーショナルデータベースを実装するように依頼しました。2つのデータ構造の違いを比較して印刷するなどの基本的な機能を使用します( //は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のこの実装。
次に、リストの中央値を計算するためのスクリプトを作成するようにモデルに促しました(以下の応答を生成します)。これは、おそらく、最も満足のいく反応の1つでした。第一に、モデルを促した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は、SILでK -Nearest Neighborsアルゴリズムを実装するように求められました。これは、モデルが最初の試行でdistancesと呼ばれるモジュールを幻覚/想定するため、実際には2つのプロンプトの結果です(以下の生成されたコードブロックで説明されています)。 2回目の試みでは、このモジュールの存在を想定せずにアルゴリズムを実装するように促しました。
ここでのChatGptのパフォーマンスは混在しています。第一に、場合によっては、SILの機能的側面を無視します(最初の試みでforループを実装するなど。実装の他の部分では、SILは機能的であり、 |>演算let map正確に採用していることを理解しています。
// 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 ])
}
機能的言語の興味深い特徴の1つは、それらが非常に表現力豊かである可能性があることです。ここでは、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は、数学的およびプログラミングの問題のコレクションです(LLMSの興味深いプロンプトになると思います)。ここでは、SILを使用して最初の2つのプロジェクトオイラーの問題を解決するように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)
LLMSがいくつかのショットで新しいプログラミング言語の特徴を推測および理解する能力を探ることは、オープンで興味深い質問のままです。ここで、これらの能力は、ChatGPTにSILと呼ばれる新しいドメイン固有の言語(DSL)で促された問題を解決するように促すという文脈で調査されました。 DSLは、LLMSでの推論と記憶を調査するための潜在的に有用なテストケースです。これは、しばしば特徴的な特徴を持ち、トレーニング中に広く遭遇する可能性が低いためです。
全体として、パフォーマンスは混合されました。CHATGPTは、このDSLが機能的なプログラミング言語であることを正しく理解していました(ただし、これを再採点する必要がある場合があります)、それに応じてソリューションを実装しました。ただし、提供されている5つの例から、このDSLの構文ルールをキャプチャすることは広く失敗しました。さらなる調査(他のDSLの使用、LLM生成コードを評価するためのより正式なメトリックの開発、モデルの学習ダイナミクスの定量化など)は、このレポの興味深い拡張になります。最後に、別のCHATGPTセッションで、このメタプロンプトを提供して、モデルが独自のSILコードをどのように解釈したかを判断しました。

ChatGPTは、ドメイン固有の言語SILでコードを作成する独自の試みを検討し、その機能のいくつかを説明します。
LLMの記憶は、トレーニングの例のプレゼンテーションの頻度と、モデルの促進に使用される関連トークンの数によって促進されるという証拠があります。 ↩