원문 출처: Mirror: An LLM-powered programming-by-example programming language

왼쪽은 예제 전용 코드, 오른쪽은 AI가 생성한 코드, 아래쪽은 프로그램 출력을 보여주는 Mirror. (이미지 출처: 원문)

"예제 기반 프로그래밍 (Programming by example)"은 사용자가 원하는 결과의 예제를 입력하면, 시스템이 그 예제를 수행할 수 있는 코드를 생성하는 것이다. 예를 들어, 엑셀에서, 한 열이 어떻게 포매팅 되어야하는지 한두개의 예시를 제공하면, 엑셀이 자동으로 포매팅 방식을 익히고 나머지 열에 적용해준다.

그렇다면 "예제 기반 프로그래밍"으로만 작성할 수 있는 언어가 있다면 어떨까? AI를 프로그래밍 언어와 결합시킬 수 있을까?

Overview of Mirror

나는 "예제 기반 프로그래밍"을 극한으로 해보고 싶었다. "Mirror" 언어에서는 몇가지 예제 입출력 쌍을 제공하는 방식으로만 함수를 정의할 수 있으며, 그렇게 만들어진 함수를 호출한다. 그게 끝이다. 모든 것이 예제로 표현되어야한다.

is_even 함수를 표현하는 아주 간단한 예제부터 시작해보자.

signature is_even(x: number) -> bool
example is_even(0) -> true
example is_even(1) -> false
example is_even(222) -> true
example is_even(-99) -> false

함수 이름, 매개변수 및 그 타입, 반환 타입을 입력한다. 그런 다음 예상 결과와 함께 하나 이상의 예제를 제공한다. Mirror는 엄격한 구문을 사용하며 몇 가지 기본 유형을 지원한다. 필요한 만큼 함수를 만든 다음 서로 연결할 수 있다.

기존의 재귀적 하강 파서(recursive descent parser)를 사용하여 구문 분석 후, '컴파일러'는 LLM을 사용하여 예제에서 표현된 제약 조건을 충족하는 JavaScript를 생성한다. 생성된 코드를 보고 올바른지 확인할 수 있고, 또는 더 많은 예제를 제공하고 다시 컴파일할 수도 있다.

함수를 호출하기 위해서는 함수를 연결하거나 리터럴을 인수로 전달할 수 있다. 그러면 생성된 JavaScript가 실행되며 각각의 결과를 출력한다.

is_even(123456)

각종 타입(numbers, bools, strings, lists, dictionaries)으로 원하는 만큼 많은 함수를 선언하고, 함수들을 체이닝할 수 있다.

그게 이 언어의 전부다.

아래는 추가 예시들:

signature foo(x: number, y: number) -> number
example foo(10, 3) = 101010
example foo(1, 1) = 1
example foo(0, 10) = 0
signature bar(x: number) -> string
example bar(9) = "length is 1"
example bar(3210) = "length is 4"
bar(foo(123, 3))
signature m(x: list[number]) -> number
example m([2,9,5]) = 9
m([6,3])
signature counts(a: string) -> dict[string, number]
example counts("food") = {"f": 1, "o": 2, "d": 1}
counts("tree")
counts("anakin")

Mirror 사용법

브라우저에서 실행할 수 있는 플레이그라운드를 만들었다. HTML 파일 하나와 JS 파일 하나를 다운로드하여 실행해볼 수 있다. OpenAI key는 자신의 것을 사용하면 된다. 다운로드는 GitHub에서 가능하다.

JS 라이브러리로 사용할 수도 있다(약간의 정리가 필요하지만).

구현

그래서, 이 멋진 작품은 어떻게 동작하는가? 두 클래스, 파서와 "컴파일러"가 있다.

파서는 간단한 재귀적 하강 파서로 세 가지를 반환한다: 함수 시그니처 객체, 각 함수에 대한 예제들, 함수 호출.
문법은 아래와 같다.

program = {signature | example | expression}
signature = "signature" name "(" parameters ")" "->" type
example = "example" name "(" literals ")" "=" literal
expression = name "(" subexpression ")"
subexpression = (expression | literal) {"," (expression | literal)}
literals = literal {"," literal}
literal = string | number | "true" | "false" | "[" literals "]" |  "{" keyvalue {"," keyvalue} "}"
keyvalue = literal ":" literal
parameters = parameter {"," parameter}
parameter = name ":" type
type = "string" | "number" | "bool" | "list[" type "]" | "dict[" type "," type "]"
// name, string, number are tokens

"컴파일러" 나머지 부분이다. 따옴표를 계속 사용하는 이유는 실제로 코드 생성을 OpenAI LLM이 수행하기 때문이다. 이 "컴파일러"는 프롬프트를 통해 예제들을 만족하는 JavaScript 함수를 생성하도록 요청한다.


Mirror는 AI가 기존 프로그래밍 언어에 어떻게 통합될 수 있는지에 대한 PoC(Proof of concept; 개념 증명)다. 자연어를 사용해 코딩하고 싶지 않다고 해서 LLM의 힘을 활용할 수 없다는 뜻은 아니다!

profile
해외 개발 관련 컨텐츠 번역. 자연스럽게 읽을 수 있는 번역을 지향합니다.

0개의 댓글

관련 채용 정보

Powered by GraphCDN, the GraphQL CDN