https://arxiv.org/pdf/2401.08500


Abstract:

  • 여기서는 코드 생성과 관련된 작업에서 일반적인 Prompt Engineering 기법 보다 다단계로 코드를 생성하고 개선하도록 하는 Flow Engineering 으로 변경시켰을 때 성능이 향상되었다는 내용을 다루는 논문임.
  • GPT-4 에서 코드 생성을 나름 최적화한 프롬프트를 했을 때 정확도는 19% 나온 반면에, AlphaCodium 의 Flow Engineering 을 적용할 경우 44% 의 정확도를 보였다고 한다.
  • 코드 생성은 일반적인 자연어 처리 작업과는 조금 다름. 복잡한 경향이 있다:
    • 프로그래밍 언어의 정확한 문법을 맞춰야 함.
    • 목표를 이룰 수 있는 정확한 실행 흐름을 가져야 함.
    • 문제에 있는 수많은 세부 조건을 고려해야함.
    • 한 글자만 다르더라도 코드가 틀려짐.

Introduction:

  • CodeContests라는 데이터셋을 도입해서 경쟁적 프로그래밍에서 코드 생성 작업을 평가함.
  • 이전에 DeepMind 에서 개발한 AlphaCode 는 경쟁적 프로그래밍 작업에 파인튜닝을 하고, 수백만개의 가능한 솔루션을 생성하고, 이를 클러스터링해서 약 10개 정도 솔루션을 내는 기법임. 코드 중심 작업에 특화된 모델을 미세 조정해야 하고, 막대한 계산 자원이 필요하다는 단점이 있다는게 문제.
  • 이 논문에서 소개하는 AlphaCodium 은 입력-출력 테스트에 대해 생성된 코드를 반복적으로 실행하고 수정하는 과정을 중심으로 이뤄짐
  • 이 처리 흐름은 자연어로 문제를 분석하는 전처리 단계와 공용 및 AI 생성 테스트에 대해 코드를 생성, 실행, 수정하는 반복적인 코드 생성 단계로 구성됨.
  • 이 처리 흐름 중의 중요한 핵심 요인은 공개된 테스트 케이스를 모두 통과할 때까지 AI 를 통해서 테스트 케이스를 추가로 만든 후 이 테스트를 통과할 때까지 코드를 반복적으로 개선하는 것임.
  • AlphaCodium 흐름을 설계할 때의 중요한 통찰 중 하나는 코드를 생성하는 작업보다 테스트 케이스를 만드는 작업이 훨씬 쉽다는 거임. 특정 테스트를 추가하는 것은 문제에 대한 이해와 약간의 통찰력, 기본적인 브루트 포스나 논리적 추론만 필요하기 때문:
    • 복잡한 작업을 한번에 하는 것보다는 복잡한 작업을 해냈다는 테스트를 만들고 이를 이용해서 반복적인 작업으로 만드는 것이 훨씬 쉬울수도.
  • AlphaCodium 흐름은 새로운 코드 중심의 디자인 개념과 트릭, 모범 사례를 제공해주기도 함:
    • YAML 구조화된 출력:
      • 코드를 구조화된 형식으로 출력하여 가독성과 분석 용이성을 높임.
    • 불릿 포인트 분석:
      • 의미론적 추론을 촉진하기 위해 문제를 불릿 포인트로 분석함.
      • 불릿 포인트는 문제에 대한 심층적인 이해를 장려하고, 모델이 출력을 논리적이고 의미론적인 섹션으로 나누도록 강제하기 때문
    • 모듈식 코드 생성:
      • 코드의 재사용성과 유지 보수성을 높이기 위해 모듈화된 코드를 생성함.
      • LLM에게 길고 단일한 함수를 생성하도록 요청하면 코드에 버그나 논리적 오류가 자주 발생함.
    • 이중 검증을 통한 유연한 결정:
      • 결정 과정에서 이중 검증을 사용하여 오류를 줄임.
      • LLM은 생각하고 추론하며 엄격하고 비직관적인 결정을 내려야 하는 코드 작업에서 어려움을 겪음.
      • 그래서 이중 검증 프로세스를 도입하여, 생성된 출력이 주어지면 모델에게 동일한 출력을 다시 생성하되 필요한 경우 수정하도록 요청하는 걸 통해서 이 문제를 보다 해결할 수 있음.
    • 탐색을 장려하고 직접적인 결정을 미루기:
      • 다양한 솔루션을 탐색하고 바로 결론을 내리지 않도록 유도함.
      • 쉬운 작업에서 어려운 작업으로 점진적인 데이터 축적 흐름을 채택함.
        • 단계 1: 가장 쉬운 작업부터 시작—문제에 대한 자기 반성 및 공개 테스트에 대한 추론.
        • 단계 2: 추가적인 AI 테스트 생성 및 가능한 솔루션 탐색으로 이동.
        • 단계 3: 위의 작업에 대한 모델의 답변을 얻은 후 실제 코드 생성과 실행-수정 반복 단계로 이동.
    • 테스트 앵커:
      • 핵심 테스트 케이스를 앵커로 사용하여 솔루션의 정확성을 확보함.
      • 단계 1: 올바른 것으로 알려진 공개 테스트에서 먼저 반복을 수행하고, 통과한 모든 테스트를 앵커 테스트로 설정
      • 단계 2: 이제 AI 생성 테스트를 하나씩 반복. 테스트를 통과하면 테스트 앵커 목록에 추가함.
      • 단계 3: 테스트가 실패하면 코드가 잘못되었다고 가정하고 코드를 수정함. (테스트가 잘못되었다는 가정 X) 그러나 수정된 코드가 이미 확보된 모든 테스트 앵커를 통과하도록 요구함. 즉 테스트 앵커를 사용하여 잘못된 수정이 이루어지지 않도록 보호 장치를 거는 것.
      • 수정된 코드가 테스트 앵커를 통과하지 못한다면, 이번에는 AI 생성 테스트가 잘못되었을 가능성을 고려하게 될거임.

 

 

AlphaCodium - Proposed Flow:

  • Overview:
    • 코드 생성 문제의 복잡한 특성 때문에, 단일 프롬프트 최적화나 Chain-of-Thought 프롬프트조차도 LLM(대형 언어 모델)의 CodeContests에 대한 정확도를 의미있게 향상 시키지 못했다고 함.
    • 모델은 문제를 이해하고 파악하는 데 어려움을 겪으며, 지속적으로 잘못된 코드를 생성하거나, 공개 테스트는 통과하지만 보이지 않는 비공개 테스트에서는 일반화에 실패하는 코드를 만들어 냈다고 한다.
    • NLP에서 사용되는 일반적인 프롬프트 엔지니어링 기술 대신, 우리는 CodeContests 문제를 해결하기 위해 전용 코드 생성 및 테스트 지향 흐름을 사용하는 것이 유익하다는 것을 발견했다고 한다.
    • AlphaCodium 흐름은 크게 다음과 같을 거임:
      • 전처리 단계:
        • AlphaCodium이 자연어로 문제에 대해 추론하는 선형 흐름.
        • 이 단계에서는 문제의 요구 사항과 세부 사항을 깊이 있게 이해하기 위해 문제를 분석하고 요약
      • 코드 반복 단계:
        • AlphaCodium이 코드를 생성하고, 실행하고, 특정 테스트에 대해 솔루션 코드를 수정하는 반복적인 단계를 포함함.
        • 이 단계에서는 이전 단계에서 얻은 통찰과 추가된 테스트 케이스를 활용하여 코드의 정확성과 일반화를 개선한다.
  • Flow stages:
    • 문제 반영(Problem reflection):
      • 문제를 불릿 포인트로 정리하는 것.
      • 문제의 목표, 입력, 출력, 규칙, 제약 조건 및 문제 설명에 나타나는 기타 관련 세부 사항을 다룸.
      • 문제를 명확히 이해하고 핵심 요소를 식별하여 다음 단계에서 활용할 수 있도록 하는게 목표.
    • 공개 테스트 추론(Public tests reasoning):
      • 각 공개 테스트 입력이 해당 출력으로 이어지는 이유를 설명
      • 테스트 케이스를 통해 문제의 로직과 요구 사항을 더 깊이 이해하고, 잠재적인 오류나 예외 상황을 파악하기 위함.
    • 가능한 솔루션 생성(Generate possible solutions):
      • 문제에 대한 2~3개의 가능한 솔루션을 자연어로 생성
      • 다양한 접근 방법을 탐색하여 최적의 솔루션을 찾기 위한 기초를 마련하는 것.
    • 솔루션 순위 지정(Rank solutions):
      • 생성된 가능한 솔루션들을 정확성, 단순성, 견고성의 기준으로 순위화하고, “최적의 솔루션” 을 선택
      • 구현하기에 가장 적합한 솔루션을 선택하여 코드 작성의 기반으로 사용
    • 추가적인 AI 테스트 생성(Generate additional AI tests):
      • 문제에 대한 6~8개의 다양한 입력-출력 테스트를 추가로 생성하는 것.
      • 원래 공개 테스트에서 다루지 않은 케이스나 측면(예: 엣지 케이스, 큰 입력값 등)을 포함하여 테스트 범위를 넓히기 위함
    • 초기 코드 솔루션(Initial code solution):
      • 문제에 대한 초기 코드 솔루션을 생성하는 것.
      • 이 단계에서 생성된 코드는 정확한 코드에 상당히 가까워야 하며, 그래야 다음 단계의 실행-수정 반복(run-fix iterations) 에서 성공 확률이 높아진댜고 함.
    • 공개 테스트에 대한 반복(Iterate on public tests):
      • 기준 코드에서 시작하여 공개 테스트에서 반복적으로 실행
      • 코드가 특정 테스트에서 실패하면, 오류 메시지를 기반으로 코드를 수정하려고 시도함.
      • 공개 테스트를 모두 통과하도록 코드를 개선하여 기본적인 정확성을 확보하기 위함.
    • AI 생성 테스트에 대한 반복(Iterate on AI-generated Tests):
      • AI가 생성한 추가 테스트에 대해 실행-수정 반복을 계속함.
      • 코드가 더 다양한 상황과 입력에 대해 올바르게 작동하도록 보장하여, 코드의 견고성과 신뢰성을 높이기 위함.

 

 

Additional insights:

  • 여기서 나온 AlphaCodium 의 처리 흐름에서 배운 추가적인 통찰은 지식 축적(knowledge accumulation) 매커니즘을 사용하는 것이다. 이건 쉬운 단계에서 어려운 단계로 진행하면서, 그 과정에서 얻은 지식과 통찰이 더 어려운 단계에서 도움을 준다는 거임. 예를 들면 첫 번째 단계인 ’문제 반영(problem reflection)’의 출력은 더 어려운 단계인 가능한 솔루션 생성(generate possible solutions) 에 입력으로 제공하는 식으로 활용될 수 있음. 그리고 이렇게 전처리 단계에서 얻은 출력들은 가장 도전적이고 중요한 단계인 코드 반복(code iterations) 단계에서 도움을 줄거임.
  • 또 AlphaCodium 을 설계할 때의 지식 축적이 사용된 사례는 AI에게 추가적인 테스트를 생성하는 것이 완전한 솔루션 코드를 생성하는 것보다 쉽다는 거임. 추가적인 테스트를 생성하려면 주로 문제에 대한 이해와 기본적인 브루트 포스나 논리적 추론이 필요함. 문제를 완전히 “해결”하지 않고도 유용한 입력-출력 테스트 쌍을 생성할 수 있음. 확실히 이는 모든 가능한 입력-출력 쌍을 정확히 해결해야 하는 완전한 알고리즘적 솔루션이 필요한 올바른 솔루션 코드를 생성하는 것과 대조적임. 이렇게 지식 축적을 활용할 수 있음.

+ Recent posts