반응형

요즘 프로그램 분석하는게 취미가 된것마냥, 여가 시간이 나면 계속 분석만 하고 있네요 ㅎㅎ 벌써 아프리카TV 프로그램 분석 주제로 세번째 포스팅을 하게 되었습니다!

 

이번 포스팅의 주제는 P2P 패킷에 대해 분석한 내용을 다루었습니다. 나름의 Handshake 과정이 있었으며, 이번 분석으로 실제 미디어 파일을 받기까지 어떠한 작업이 이루어졌는지 알 수 있었는데요. 프로그램이 좀 방대하지만 이 포스팅에서는 720p 영상에 한하여 분석한 내용이 있으니 참고하셔서 봐주세요 :D

1. 통신 순서

이 프로그램에서 P2P 통신을 할 때 나름의 명칭이 있었는데요.(물론, 다른 P2P에서도 동일한 네이밍을 쓸수도 있음)

 

데이터를 요청하는 시청자를 Child, 영상 데이터를 제공해주는 시청자를 Parent라고 합니다. 나의 역할이 무엇인지에 따라서 Child와 Parent로 나뉘지만, 이 글에서는 Child 입장에서 글을 풀어가겠습니다.

 

Child 시청자는 인터넷 방송을 보기위해 방송을 들어갑니다. 이 때는 아프리카TV 프로그램 분석 (2) - Grid Network 글에서 다루었다시피, 각종 정보를 주고받고 Parent시청자의 정보도 획득하게 되는데요. Parent 시청자 정보를 받게된 후에는 아래 그림과 같은 Flow로 통신이 이루어지며, 실시간 스트리밍 영상을 전달받게 됩니다.

Communication with ParentHost

 

각 Flow 별 설명이 간단히 풀어보면 아래와 같습니다. 참고로 Command로 적힌 항목은 이 프로그램에서 정의해둔 2Byte 정수인데요. 아프리카TV 프로그램을 분석하다보면 매우 다양한 Command가 있지만, 기본적인 통신에 필요한 아래 4개의 Command만 다루겠습니다.

 

1) V2S_REQ_BROADCAST_STREAM_VER2

  • 통신 흐름: Child (me) -> Parent
  • Command: 0xCB2E
  • 설명: 상대 사용자(Parent)에게 P2P Stream 데이터 요청합니다.

2) P2P_ACK_BROADCAST_STREAM_RIGHT_VER2

  • 통신 흐름: Parent -> Child (me)
  • Command: 0x1BC7
  • 설명: Child(me) 요청에 대한 응답으로써, 스트리밍의 프레임 정보를 Child(me)에게 전달합니다.

3) V2S_REQ_CACHE_DATA_VER2

  • 통신 흐름: Child (me) -> Parent
  • Command: 0xCB30
  • 설명: 재생에 필요한 프레임 정보를 상대 사용자(Parent)에게 요청합니다.

4) S2V_REP_CACHE_DATA_VER2

  • 통신 흐름: Parent -> Child (me)
  • Command: 0xC748
  • 설명: 실제 스트리밍 미디어 데이터를 Child(me)에게 전달합니다.

2. 패킷 뜯어보기

앞서 다루었던 각 Flow의 패킷을 조금 더 세밀하게 뜯어보도록 하겠습니다. Child와 Parent는 일반적인 TCP 통신을 하며, 별도의 암호화 절차는 없었습니다. 그도 그럴것이 실시간 영상데이터인데 암복호화가 이루어지면 처리 시간이 평문일 때보다 더 걸릴 수도 있을 것 같네요. (혹시라도 실시간 영상에도 암호화가 이루어진다면 관련해서 댓글 부탁드립니다! 저도 이 분야는 처음이라..ㅎㅎ)

 

무튼 모든 데이터는 크게 Header와 Body로 구성되어 있는데요. Header는 0x10 byte이며, Body는 나머지 하위 데이터들입니다. 또한 Header의 구조는 모든 Command가 동일한 반면에 Body의 구조는 Command별로 다 달랐습니다! 그럼 각 항목별로 데이터를 소개드리겠습니다.

 

1) V2S_REQ_BROADCAST_STREAM_VER2 (ME -> PARENT)

  • 패킷 캡쳐

V2S_REQ_BROADCAST_STREAM_VER2

 

  • Header (파란색 박스)
    Version Info (2byte): 0x202 # Default
    Command (2 byte): 0xCB2E # V2S_REQ_BROADCAST_STREAM_VER2
    Body Size (4 byte): 0x0000000c
    Check Sum (4byte): 0x0000C920 # checksum = version ^ command ^ body_size
    ??? (4byte): 0x19F928
  • Body (빨간색 박스)
    Broad Cast ID (4byte) : 0x0ee7cba1 # 생방송 ID
    Node Key (4byte) : 0x000014b8 # Child(me)의 ID
    Quality (4byte) : 0x00000001 # 화질 정보 (1=720p, 4=540p, 8=360p)

2) P2P_ACK_BROADCAST_STREAM_RIGHT_VER2 (PARENT -> ME)

  • 패킷 캡쳐

P2P_ACK_BROADCAST_STREAM_RIGHT_VER2

  • Header (파란색 박스)
    Version Info (2byte): 0x202 # Default
    Command (2 byte): 0x1BC7 # P2P_ACK_BROADCAST_STREAM_RIGHT_VER2
    Body Size (4 byte): 0x00000018
    Check Sum (4byte): 0x000019DD # checksum = version ^ command ^ body_size
    ??? (4byte): 0x544c5553 # garbage data?
  • Body (빨간색 박스)
    Quality (4byte) : 0x00000001 # 화질 정보 (1=720p, 4=540p, 8=360p)
    Last Frame Number (new) (4byte) : 0x0030df54
    Last Frame Number (before) (4byte) : 0x00000000
    Last PTS (new) (4byte) : 0xc1c80d3b # PTS: 재생 시간 타임스탬프 (Presentation Timestamp)
    Last PTS (before) (4byte) : 0x00000610
    ??? (4byte) : 0x00000001 # 처리 로직이 안보이네요;

3) V2S_REQ_CACHE_DATA_VER2 (ME -> PARENT)

  • 패킷 캡쳐

V2S_REQ_CACHE_DATA_VER2

  • Header (파란색 박스)
    Version Info (2byte): 0x202 # Default
    Command (2 byte): 0xCB30 # V2S_REQ_CACHE_DATA_VER2
    Body Size (4 byte): 0x00000010
    Check Sum (4byte): 0x0000C922 # checksum = version ^ command ^ body_size
    ??? (4byte): 0x00D8D210
  • Body (빨간색 박스)
    Status (4byte) : 0x00000001 # 해상도?
       # {1: Original, 2: 2000K, 4: 1000K, 8: 500K, 0x10: 4000K, 0x20: 8000K}
    Last Frame number (new) (4byte) : 0x0030DF5C
    Last Frame number (before) (4byte) : 0x00000000
    ConnectStatus  (4byte): 0xFFFFFFFF # 최초연결: 0xffffffff, 기존연결: 0x00000006

4) S2V_REP_CACHE_DATA_VER2 (PARENT -> ME) // 영상데이터

  • 패킷 캡쳐

S2V_REP_CACHE_DATA_VER2

  • Header (파란색 박스)
    Version Info (2byte): 0x202 # Default
    Command (2 byte): 0xC748 # S2V_REP_CACHE_DATA_VER2
    Body Size (4 byte): 0x0000047b
    Check Sum (4byte): 0x0000C131 # checksum = version ^ command ^ body_size
    ??? (4byte): 0x00000000
  • Body (빨간색 박스)
    Header (2byte) : 0x0001
    Size of header in body (2byte) : 0x0045
    Extention Size (4byte) : 0x00000000
    Raw data size (4byte): 0x00000436
    iFrameNo (4byte) : 0x0030df5c
    
    # 아래 부터는 부분적인 분석만 되어서 분석된 내용들만 등록합니다 ㅠㅠ
    Frame Type (1byte. offset: 0x28): 0x50 # {"A": "AAC", "I": "H264", "P": "H264"}
    media raw data (0x45 ~ Raw data size 만큼의 크기) # ts파일의 body만 있는듯 합니다. 
    				 	 	 # 영상으로 변환은 다음 포스팅에서 소개하겠습니다.

3. POC

끝으로, 위에서 분석한 내용을 토대로 Parent 사용자에게 영상 데이터를 요청하는 POC를 작성해보았습니다. 물론, 다른 시청자가 아니고 제가 아프리카 방송을 켜고 저의 PC와 VM만으로만 테스트 했습니다 :)

 

1) 테스트 환경 이미지

Testing Environment

 

2) POC 결과 이미지

POC

반응형

지난 포스팅에 이어서 고화질 스트리머 프로그램 분석글을 작성하겠습니다. 이 전 포스팅에서는 스트리밍 데이터를 받기 전에 어떠한 작업들이 이루어지는지 알아보았는데요. 이번 포스팅에서는 영상 데이터를 어디서 받아오는지를 중심으로 내용을 구성해보았습니다. 또한 Frida로 바이너리를 후킹하여 원하는 정보를 쉽게 받아오는 스크립트도 함께 소개드리겠습니다.

1. Client와 Center 서버간의 통신

이 전 포스팅에서 afreecastreamer.exe를 실행하고, 실시간 방송을 재생하면 Center로 불리는 아프리카 서버 (TCP PORT:19000)로 연결되는 것을 확인하였습니다. 이 Center와 연결한 후에는 다양한 작업을 하지만, 눈에 띄는 몇 가지만 나열해보면 아래와 같습니다.

1) Client -> Center

  • 사용자의 각종 설정 값을 전달 함
  • UUID, OS, Language 등을 비롯한 기본 정보도 전달되며,
  • path_key, ticket과 같이 Center와 연결에 필요한 식별 정보도 함께 전달됨
  • 참고) UUID와 path_key가 동일한 값
    Send data from Client to Center

2) Center -> Client

  • 1440p 지원여부, 인증정보 등 방송 정보를 전달하며,
    Send information from Center to Client (1)
  • 실시간 방송의 채팅방 정보(broadno, chat IP, chat Port, chat roomno, title)를 전달함
    Send information from Center to Client (2)
  • Parent IP, Parent Port라는 정보를 전달함 (다음 목차에서 Detail하게 다룰 내용)
    • 아래 이미지는 최초로 제공되는 Parent IP, Port 이며, 스트리밍 데이터를 제공해주는 Host
      Main parent
    • 추가로 3개의 Parent IP와 Port를 제공 받으며, 아마도 예비용 Parent 정보로 보여집니다.
      Sub parents

2. Client와 Client간의 통신

1) Grid Network

Grid Network라고 함은 쉽게 말해 사용자들끼리의 네트워크를 연결하여 형성한 것을 의미합니다. 보통의 인터넷 서비스들은 Server와 Client와 같이 1대 다수가 연결하는 망구조 인데요. 스트리밍 서비스에서 이런 네트워크 구조를 가진다면 Server에 적지않은 부담이 갈 것이고, 흔히 말하는 버퍼링이 발생할 가능성이 높아집니다.
하여, 아프리카TV를 포함한 각종 라이브 스트리밍 서비스에서는 Grid Network를 체택하였는데요.(Grid 프로그램 설치시에만 구성됨) 이는 동일한 라이브 스트리밍 영상을 보는 사용자들끼리 Live Cache(또는 Streaming Cache) 데이터를 공유하도록 함으로써, 서버의 부담을 줄이면서 사용자에게 빠른 영상과 화질을 제공해줄 수 있게 됩니다.

2) 스트리밍 영상 제공자

A) Parent IP와 Port에 대하여

우선 위에서 잠깐 나온 Parent IP, Parent Port라는 키워드부터 짚고 가겠습니다. 이 키워드는 아프리카TV의 개발자분들이 정의해둔 이름으로 보입니다. 프로그램을 분석하면서 알게된 결과, ParentIP는 실시간 영상 정보를 에게 전달해주는 노드이며, Parent Port는 이 노드와 연결할 포트입니다. 이러한 IP와 Por 정보는 AfreecaTV의 Center로부터 전달받게 되는데요. Center의 내부 로직이 어떻게 되어있는진 모르겠으나, 아마도 같은 라이브 방송을 시청하고 있는 다른 사용자의 IP와 Port를 전달해주는 듯 합니다.

그도 그럴것이 Parent Port의 범위는 보통 10000 ~ 100xx로 보여지는데요. 저의 PC에서도 afreecastreamer.exe를 실행하니, 동일한 대역의 Port를 열고 Listening하는 것을 확인할 수 있었습니다.

Listen ports of Afreecastreamer.exe

B) Parent IP, Port의 형태 변환

분석 초반에 Network Packet에서 Parent IP와 Port를 접하게 되었습니다. 제공되는 형태는 JOSN 포맷에 묶여져서 전달되었으며, IP와 Port의 Type은 10진수로 전달되었는데요. 전달받은 10진수를 IP형태로 변환을 해보아도 실제 통신을 하고있지 않은 뜬금없는 IP가 나왔으며, Port 또한 전혀 생뚱많은 값이었습니다. 이 값들은 AfreecaTV의 Center에서 IP/Port 정보를 Little Endian 방식으로 변환한 후에 각 Client에게 제공해주고 있었는데요.

우선 Wireshark로 실제 패킷을 제공해주고 있는 Parent IP와 Port를 보면 IP는 222.109.223.157이고 Port는 10030인것을 알 수 있습니다.

Receive data from parent host

그리고 아래 데이터는 포스팅 초반에 언급되었던 Parent IP와 Parent Port인데요. 아래의 형태로 Center 서버로부터 전달받았으며, 10진수의 값들을 IP형태로 변환해본 코드입니다.

  • Center로 부터 전달받은 데이터 ("parent_ip":2648665566, "parent_port":11815)
    {"list":[{"cur_frame_no":29474472,"cur_pts":0,"cur_seq_audio":950753,"cur_seq_video":28523717,"parent_ip":2648665566,"parent_port":11815,"parent_sess":22266,"quality":1,"skip_frame":0}]}
  • 단순 IP 및 Port 형태로 변환
    ip = 2648665566
    port = 11815
    ip_1 = (ip & 0xff000000) >> 0x18
    ip_2 = (ip & 0xff0000) >> 0x10
    ip_3 = (ip & 0xff00) >> 0x8
    ip_4 = (ip & 0xff)
    print(f"Parent IP: {ip_1}.{ip_2}.{ip_3}.{ip_4}:{port}")
    
    # Outupt: Parent IP: 157.223.109.222:11815

예상과는 다른 결과가 나와서 놀랐습니다. 실제 네트워크 패킷에서의 Source IP는 `222.109.223.157`이고 Port는 `10030`이었지만, 10진수를 단순히 IP형태로 변환한 코드에서는 `157.223.109.222:11815`가 출력되었습니다.

눈치채신분은 "아, IP가 거꾸로 출력되었네?"라고 인지가 되었을텐데요. 추측컨데 이는 Center에서 Parent 정보를 Client에게 전달해줄 때 Little Endian 방식으로 그대로 전달을 해준듯하구요. Port도 Little Endian 일것이라고 판단하여, 아래의 스크리립트로 다시 변환을 해보니 원하는 Parent IP와 Port를 획득할 수 있었습니다.
 

  • Little Endian형태의 10진수를 IP및 Port 형태로 변환
import struct 
parent_ip = 2648665566 
parent_ip = struct.pack("<I", parent_ip) 
parent_ip = struct.unpack(">I",parent_ip)[0] 
ip_1 = (parent_ip & 0xff000000) >> 0x18 
ip_2 = (parent_ip & 0xff0000) >> 0x10 
ip_3 = (parent_ip & 0xff00) >> 0x8 
ip_4 = (parent_ip & 0xff) 
print(f"Parent IP: {ip_1}.{ip_2}.{ip_3}.{ip_4}") 

parent_port = 11815 
parent_port = struct.pack("<I", parent_port)[:2] 
parent_port = struct.unpack(">h", parent_port)[0] 
print(f"Parent Port: {parent_port}") 
''' 
# Output 
Parent IP: 222.109.223.157 
Parent Port: 10030 
'''

C) Frida를 이용한 Parent IP, Port 정보 획득

그럼 이 Parent IP와 Parent Port에 대한 정보를 좀 더 손 쉽게 구할 방법을 고안하다가, Frida를 이용하여 afreecastreamer.exe 메모리에서 받아서 출력해주는 방식을 생각해보았습니다. 분석을 좀 용이하게 하기 위해서 작성한 Script이며, "이런 방식으로 정보를 수집할수 있다"정도의 참고로만 봐주세요.

  • 후킹할 지점 (module: NetControl.dll, offset: 0xe5dd)
    • Disassembly
    • Hex-ray
  • Frida Code
import frida, sys
import struct

def get_parent_info():
    # Frida JavaScript 코드
    script_code = """
    // 모듈과 함수 이름
    var moduleName = 'NetControl.dll';
    var offset = 0xe5dd;

    // 모듈 가져오기
    var module = Process.getModuleByName(moduleName);
    var hook_addr = module.base.add(offset);

    // 후킹
    Interceptor.attach(hook_addr, {
        onEnter: function (args) {
            var stack = this.context.esp;
            var ip = Memory.readPointer(stack.add(0x50), 4);
            var port= Memory.readPointer(stack.add(0x54), 2);
            send({ parent_ip: ip, parent_port: port });
        },
        onLeave: function (retval) {
        }
    });
    """
    return script_code
    
def on_message( message, data ):
    payload = message["payload"]
    if "parent_ip" in payload:
        # parent_ip, parent_port가 little endian으로 지정되어 있어서, 비트연산을 해주어야 원래 값이 나온다.
        parent_ip = int(payload["parent_ip"], 16)
        parent_port = int(payload["parent_port"], 16)
        parent_port = struct.pack("<I", parent_port)[:2]
        parent_port = struct.unpack(">h", parent_port)[0]
        print( f"[Grid Node] {parent_ip&0x000000ff}.{(parent_ip&0x0000ff00)>>0x8}.{(parent_ip&0x00ff0000)>>0x10}.{(parent_ip&0xff000000)>>0x18}", parent_port)

def main():
    process = "afreecatvstreamer.exe"
    session = frida.attach( process )
    fsc = get_parent_info() 
    script = session.create_script( fsc)


    script.on( "message", on_message )
    script.load()
    print("=======================================")
    print("[!] Ctrl+D on UNIX, Ctrl+Z on Windows/cmd.exe to detach from instrumented program.\n\n")
    sys.stdin.read()
    session.detach()
    
if __name__ == "__main__":
    main()
  • 실행 결과
Get parent info using frida script

3. 마치며

핳, 기술글을 시리즈로 쓰는것도 쉽지 않은 작업이네요. 마음같아서는 스트리밍 동영상을 처리하는 로직을 다음편에 작성하고 마무리 하고 싶은데요. 아직 분석이 완벽히 끝난게 아니라, 언제 또 작성할진 모르겠습니다! 무쪼록 기회가 된다면 이어서 써보도록 하며, 긴 글 읽어주셔서 감사드립니다 :)

반응형

오늘은 갑자기 호기심이 생긴 아프리카TV의 프로그램을 분석해보았습니다. 좀 더 정확히 말하자면, 아프리카TV의 영상을 1080P 고화질로 볼 수 있도록 하는 고화질 스트리머라는 프로그램인데요. 이 고화질 스트리머라는 것은 그리드 딜리버리 프로그램이라고 하여, 사용자들간의 데이터를 교류하며 딜레이 및 화질을 개선하기 위한 프로그램이라고 하는데요. 과연 어떤식으로 수행되는지 궁금하여 분석을 좀 시도해보았습니다.

 

최종 목표는 바이너리 분석까지 진행하고 내부에서 어떤 일이 일어나는지 작성하는 것이었으나, 아무래도 본업이 있는지라 많은 시간을 투자하진 못했구요. 프로세스 상태와 네트워크 변화들을 중심으로 분석한 내용들이니 참고하여 재밌게 봐주세요. (+기술적인 내용은 별로 없음..)

 

1. 프로세스

가장 먼저 프로그램을 설치한 후 process list를 확인해보면 아래와 같이 afreecatvpackage.exe가 실행되고 있는 것을 볼 수 있습니다. 이뿐 아니라 웹 브라우저에서 고화질로 동영상을 재생할 경우, 추가으로 afreecatvstreamer.exe라는 프로세스가 하나 더 실행되는데요. 이 프로세스가 핵심요소로 보여집니다.

1) afreecatvpackage.exe

  • PATH: %HOMEPATH%\AppData\Local\afreeca\afreecatvpackage.exe
  • Process List
  • Listening

2) afreecatvstreamer.exe

  • PATH: %HOMEPATH%\AppData\Local\afreeca\afreecatvstreamer.exe
  • Process List

3) 기타 설치된 프로그램들

  • PATH: C:\Users\사용자\AppData\Local\afreeca\
  • List
    Afreeca TV 설치파일

2. 네트워크

글로 설명하기엔 너무 복잡하여 네트워크 연결 및 수행하는 작업을 그림으로 순차적으로 그렸습니다.

1) 네트워크 초기 설정

Local Network

  • 브라우저가 Client가 되며, afreecatvpackage.exe 프로세스가 Web socket 서버가 되어 통신을 함
  • 이 구간에서는 네트워크 연결을 위해 프로세스와 브라우저간의 초기 설정을 진행
  • 또한 스트리밍에 핵심이 되는 afreecatvstreamer.exe 파일이 실행됨
  • 참고
    • HTMLPLAYER_PORT: 웹 브라우저로 스트리밍 데이터를 전송하기 위한 포트
    • HLS_PORT: HTTP Live Streaming 용 포트인데, 아프리카TV에서 언제 활용되는지 모름
    • RTMP_PORT:Real Time Messaging Protocol 용 포트인데, 아프리카TV에서 언제 활용되는지 모름

2) 방송 정보 설정 및 로깅

Afreeca Network

  • afreecatvpackage.exe 는 프록시 느낌으로 활용되어 지며,
  • Afreeca Server 중에서도 Gate 및 Center 서버로부터 방송 정보를 주고받음
  • 샘플 데이터
    • (Send )브라우저-> HTMLPLAYER_PORT
      {"SVC":40,"RESULT":0,"DATA":{"gate_ip":"218.xxx.xxx.xxx","gate_port":3456,"center_ip":"110.xxx.xxx.xxx","center_port":19000,"broadno":249417161,"cookie":"","guid":"xxxxxxxxx~~","cli_type":42,"passwd":"","category":"00570002","JOINLOG":"log\u0011\u0006&\u0006uuid\u0006=\u00064b05002dc64e43052a2dd6a8ba378d42\u0006&\u0006geo_cc\u0006=\u0006KR\u0006&\u0006geo_rc\u0006=\u000641\u0006&\u0006acpt_lang\u0006=\u0006ko\u0006&\u0006svc_lang\u0006=\u0006ko_KR\u0006&\u0006os\u0006=\u0006win\u0006&\u0006is_streamer\u0006=\u0006true\u0006&\u0006is_row_latency\u0006=\u0006false\u0006&\u0006is_rejoin\u0006=\u0006false\u0006&\u0006is_auto\u0006=\u0006false\u0006&\u0006is_support_adaptive\u0006=\u0006true\u0006&\u0006uuid_3rd\u0006=\u000xxxxxxxxa2dd6a8ba378d42\u0012liveualog\u0011\u0006&\u0006is_clearmode\u0006=\u0006false\u0012","BJID":"xxxxxxxx","fanticket":"xxxxxxxxxad6ea4b05c_xxxxxx_2xxxx1_html5","addinfo":"ad_lang\u0011ko\u0012is_auto\u00110\u0012","update_info":0}}
    • (recv) HTMLPLAYER_PORT -> 브라우저
      {"DATA":{"cSkinFile":"ps_Afreeca","cUserId":"","iExpireTime":0,"iFreeEventType":0,"iIpAddr":0,"iKeepAliveTime":330,"iMode":2},"RESULT":0,"SVC":41}

3. To be continue..

처음 시작은 전체적인 flow만 심플하게 정리하고 끝내야지라는 마음이었지만, 작성하다보니 간단하게 줄일 수 있는 내용이 아니었네요. :(
이번 포스팅에서는 실제 방송 데이터를 받기 전 단계까지의 내용만을 다루었는데요. 분석한게 좀 더 남아있으니, 다음 포스팅에 이어서 나머지것들도 작성해보도록 하겠습니다.

반응형

추천 글

Code LLaMA 공개 ><'"

Meta AI가 선보인 새로운 대화형 언어 모델인 Code Llama에 대해 이야기해보려 합니다. 이 모델은 텍스트 프롬프트를 활용하여 코드를 생성하고 토론할 수 있는 대용량 언어 모델(Large Language Model, LLM)입니다.

Code LlamaLLaMA2 모델을 기반으로 하여 생성되었으며, 코딩 작업에 있어서 현재까지 공개적으로 이용 가능한 LLM 중 가장 최신 기술을 적용한 모델로, 개발자들의 작업을 효율적으로 만들어주고 코딩을 배우는 사람들에게도 도움을 줄 수 있을 듯합니다.

Code Llama 성능 비교

1) 테스트 방법

  • Code Llama의 성능 평가를 위해 두 가지 인기 코딩 벤치마크인 HumanEvalMostly Basic Python Programming (MBPP) 을 사용함.
  • 정의
    • HumanEval: 모델이 docstrings을 기반으로 코드 완성을 수행하는 능력을 테스트
    • MBPP: 모델이 설명을 기반으로 코드 작성을 수행하는 능력을 테스트함.

2) 테스트 결과

  • Code Llama는 오픈 소스 코드 전용 LLM보다 더 나은 성능을 보이며, Llama2보다도 우수한 성과를 달성함. (아직 GPT4 보다는 낮네요 ㅠㅠ)
  • Code Llama 34B 모델은 HumanEval에서 53.7%, MBPP에서 56.2%의 점수를 기록함.
  • 이는 다른 최첨단 오픈 솔루션과 비교하여 가장 높은 점수를 달성

3) Performance Table

Code Llama의 맛보기

Code Llama는 개발자들의 작업을 보다 효율적으로 만들어주며, 코딩을 배우려는 입문자들의 진입 장벽을 낮추는 데 도움을 줄 수 있습니다. 이 모델은 코드 생성 및 코드 관련 자연어 생성에 특화되어 있어서, 코드와 자연어 프롬프트로부터 코드 및 자연어에 대한 코드를 생성할 수 있습니다.

예를 들어, "피보나치 수열을 출력하는 함수를 작성하세요"와 같은 프롬프트로부터 코드를 생성할 수 있을 뿐만 아니라, 코드 완성 및 디버깅과 같은 작업에도 활용될 수 있습니다. Python, C++, Java, PHP, TypeScript (JavaScript), C#, Bash 등 오늘날 가장 인기 있는 프로그래밍 언어를 지원한다는 점도 주목할 만합니다.

모델 종류

Code Llama는 7B, 13B 및 34B 파라미터 크기의 세 가지 다양한 모델을 공하였구요. 각 모델은 500B 토큰의 코드 및 코드 관련 데이터로 훈련되었으며, 이 중 7B와 13B 모델은 FIM 기능을 포함하여 코드 완성 작업을 지원했다고 합니다. 파라미터 크기가 작은 모델은 낮은 대기 시간이 필요한 실시간 코드 완성과 같은 작업에 적합하며, 34B 모델은 더 나은 코딩 지원을 제공합니다.

또한 Code Llama의 두 가지 특화된 변형도 소개되었습니다.

1) Code Llama - Python

- Code Llama의 언어 특화 변형으로, Python 코드의 100억 토큰에 더 세밀하게 조정되었습니다. 
- Python은 코드 생성에 가장 많이 벤치마킹된 언어이며, Python과 PyTorch가 AI 커뮤니티에서 중요한 역할

2) Code Llama - Instruct

- 지시어(Instruct)를 통해 훈련된 변형으로
- 프롬프트의 사용자가 기대하는 결과를 더 잘 이해하고 도움과 안전한 답변을 생성할 수 있도록 조정됨

끝으로

다음에는 Code Llama 모델을 이용하여 Local Machine에 셋팅하는 방법을 소개드리겠습니다. 전반적인 골조는 이전에 작성한 "LLaMA.cpp를 기반으로 한 코딩 Asistant 프로젝트 (Copilot 대체하기)"와 비슷할 듯 하구요. 포스팅 글이 올라오기 전에 Coding Asistant를 사용해보고 싶으시다면, 이전 글을 참고해주세요 :)

참고

+ Recent posts