반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형

이번에는 Openai cookbook 을 통해 얻은 정보를 가지고 embedding에 대한 예제 소스를 만들어 보도록 하겠습니다.

openai cookbook은 openai에서 제공하는 예제들이 있는 페이지 입니다.

 

https://github.com/openai/openai-cookbook

 

GitHub - openai/openai-cookbook: Examples and guides for using the OpenAI API

Examples and guides for using the OpenAI API. Contribute to openai/openai-cookbook development by creating an account on GitHub.

github.com

 

이 중에 Embeddings 부분으로 가게 되면 총 8개의 링크가 있습니다.

 

 

이 중 가장 처음에 있는 text comparison examples 로 갑니다.

 

그러면 Text comparison examples 가 나오게 되는데 오늘 다룰 부분은 예제로 곧바로 가지 않고 이 페이지에서 소개 된 블로그 중 한 곳의 내용을 가지고 소스 코드를 만들 계획입니다.

 

 

2022년 1월 블로그로 갑니다.

 

이곳에는 openai에서 embedding 기능을 선보이면서 설명한 내용이 있습니다.

 

이 내용도 읽어 보시면 Embedding을 이해하는데 아주 도움이 많이 됩니다.

 

이 페이지에서 핵심 내용은 아래 그림입니다.

 

이것은 각 아이템별로 embedding 값을 가지고 그 위치를 좌표에 표시한 것입니다.

 

feline (고양이류) friends say 에서 가장 가까운 것은 meow (야옹) 입니다.

canine (개과) companions say 에 가장 가까운 것은 woof (멍멍) 이구요.

bovine (소과) buddies say 에 가장 가까운 것은 moo (음메) 입니다.

 

미식축구의 쿼터백은 이들과는 아주 멀리 떨어져 있죠.

 

이렇게 Embedding 값은 여러 아이템들의 유사성을 비교할 수 있도록 해 줍니다.

 

이 표 아래에 보시면 아래 소스 코드가 나옵니다.

 

여기서 PRINT RESPONSE를 클릭하면 아래 처럼 보입니다.

 

아주 간단한 request와 response 인데요.

이 간단한 요청과 응답에 대해서는 바로 전 글에서 자세히 설명 했습니다.

 

https://coronasdk.tistory.com/1260

 

Open AI API - GPT 3 - Embedding API 예제 살펴 보기

오늘은 Open AI API 에서 제공하는 기본 Embedding 예제 소스 코드를 살펴 보겠습니다. 아래 글을 보시면 해당 API 페이지의 내용을 보실 수 있습니다. https://coronasdk.tistory.com/1237 Embeddings - openai.Embedding.c

coronasdk.tistory.com

 

오늘은 이것을 어떻게 의미있게 사용할 지에 대해 알아보겠습니다.

 

저는 위에 제시된 3개의 동물과 3개의 울음소리가 서로 얼마나 유사성이 있는지 알고 싶었습니다.

 

그래서 첫번째로 한 일은 request에 위의 6가지 (각 동물들과 그 울음소리) 정보를 모두 보내는 일을 했습니다.

우선 각 요소별 embedding 값을 받아야지 서로 비교할 수 있으니까요.

 

9번째 줄 까지는 계속 사용했던 부분이니까 설명은 생략하겠습니다.

 

우선 inputVal 이라는 변수에 이 6개의 아이템을 배열로 담았습니다.

 

그리고 openai.Embedding.create() 에 이를 input 값으로 보냈습니다.

여기서의 목적은 유사성을 알아보는 것이라서 모델은 text-similarity-ada-001을 사용했습니다. 

davinci 보다 성능은 떨어지지만 저렴한 ada 모델을 썼습니다.

 

일단 이 값을 pprint를 이용해서 출력 해 봤습니다.

 

어마어마하게 긴 response를 받았습니다.

 

 

입력값이 6개 이므로 index는 0~5로 총 6개의 embedding 값을 받았습니다.

토큰은 총 19개 이군요.

 

일단 입력한 6개 아이템들에 대한 임베딩값을 받았으니 그 값들을 비교해서 유사성을 추출해 내면 됩니다.

이전 글에서 살펴 봤듯이 하나의 입력 아이템 당 1536개의 부동 소숫점 배열을 응답으로 받았습니다.

이것을 그냥 비교하기는 불가능 합니다.

 

여기에서 파이썬에 있는 numpy 모듈의 dot() 메소드를 사용해야 합니다.

 

우선 그 방법을 알아보기 위해서 두개의 입력값에 대한 임베딩 값을 비교해 보겠습니다.

 

방법은 간단합니다. 

우선 첫번째 입력값과 두번째 입력값을 각각 변수에 담습니다.

첫번째 입력값은 feline friends go 이고 두번째 입력값은 meow 이었죠.

 

이 두 임베딩 값을 dot() 메소드에 파라미터 값으로 전달합니다.

여기서 return 받은 값은 similarity_score1 에 저장이 됩니다.

 

그리고 이 값을 출력해 보겠습니다.

 

 

위와 같은 값이 나왔습니다.

이제 사람이 좀 알아 볼 수 있는 값이 나왔네요.

두 아이템간의 유사성은 0.8432 ...... 입니다.

 

이제 방법을 찾았으니 모든 6개 입력값들을 짝을 지어서 유사성을 알아 보겠습니다.

동물과 울음소리가 각각 3개씩 이니까 총 9본을 비교해 보면 되겠네요.

 

일단 무식하지만 이 작업을 하나 하나씩 아래와 같이 스크립팅을 해 봤습니다.

 

이 코드의 결과는 아래와 같습니다.

 

이제 거의 다 왔습니다.

 

이제 두가지 작업만 더 하죠.

 

우선  고객이 알기 쉽도록 표시해 줍시다.

 

이런식으로 두개의 입력값에 대한 유사성은 이렇다라고 문장으로 보여 주려고 하는데요.

이렇게 하면 아래 에러가 뜹니다.

 

입력값은 string 이고 유사성에 대한 값은 numpy.float64 이기 때문입니다. 

다 string 타입으로 통일 시켜야 겠습니다.

방법은 간단합니다. numpy.float64 를 srt() 로 감싸 주면 됩니다.

 

출력값은 아래와 같습니다.

 

 

이제 고객의 요구조건에 딱 맞는 결과물을 제공할 수 있게 되었습니다.

 

고양이과의 울음소리는 meow 가 가장 유사성이 있네요.

개과도 meow로 나오는데 아마 ada 모델이 성능이 조금 떨어져서 그럴 겁니다.

ada 모델은 woof 보다 meow 가 개 울음소리에 더 가깝다고 보는 것 같습니다.

davinci 모델을 사용하면 답변이 제대로 나올 겁니다.

소과의 울음소리는 moo 가 가장 유사성이 있네요.

 

결과물의 퀄리티는 좀 떨어집니다. 이럴 경우 돈을 더 써서 davinci 모델을 사용해서 고객에게 전달을 해야지 제대로 판매를 할 수 있겠네요.

 

지금은 API 기능을 배우는 중이라 결과물에 대한 퀄리티는 크게 신경 쓰지 않겠습니다.

 

근데 결과값은 제대로 나왔지만 프로그래머로서 코드가 마음에 안 듭니다.

 

이 긴 부분은 패턴이 있기 때문에 충분히 refactoring을 할 수 있습니다.

 

for 루프를 이용해서 아래와 같이 만들어 보았습니다.

 

inputVal의 아이템 숫자 (6) 만큼 루프를 돌리면서 일을 할 겁니다.

2로 나누어 지면 즉 0,2,4번째 아이템일 경우 그 다음 일을 합니다.

즉 고양이, 개, 소 인 부분에서 3가지 울음 소리와 비교하려고 이렇게 한 겁니다.

 

두번째 for 루프는 울음 소리를 x에 담기 위해서 만들었습니다.

range(1,6,2) 의 의미는 1서부터 시작해서 6까지 2단계씩 뛰면서 x에 그 값을 담아라 입니다.

즉 첫번째 루프에서는 1이 그 다음은 2단계 뛴 3이 그리고 마지막엔 5가 담깁니다.

 

여기서 index 값에는 동물들이 있는 위치값이 그리고 x에는 울음소리가 있는 위치값이 담깁니다.

 

이걸 가지고 그 밑에 줄에서 이용을 합니다.

 

resultVal = inputVal[index] + ' and ' + inputVal[x] + ' is ' + str(np.dot(resp['data'][index]['embedding'], resp['data'][x]['embedding']))

그리고 이 값을 resultList 에 append 합니다.

 

이렇게 하면 위에 26줄에 걸쳐서 했던 일을 10줄도 안되게 줄일 수 있습니다.

 

 

답변도 위에서와 같이 나옵니다.

 

아마 22번째 줄을 좀 더 가시성이 있도록 바꾸고 싶으신 분들도 많을 겁니다.

저도 좀 그런데... 오늘은 그냥 여기까지 하겠습니다.

 

이렇게 해서 Openai API 중에서 Embedding 기능을 유의미하게 사용하는 방법을 살펴 봤습니다.

 

완성된 소스 코드는 아래와 같습니다.

 

import openai
from pprint import pprint
import numpy as np

def open_file(filepath):
    with open(filepath, 'r', encoding='utf-8') as infile:
        return infile.read()

openai.api_key = open_file('openaiapikey.txt')

inputVal = ["feline friends go", "meow","canine companions say" , "woof", "bovine buddies say", "moo"]

resp = openai.Embedding.create(
    input=inputVal,
    model="text-similarity-ada-001")
    #model="text-similarity-davinci-001")
    
resultList = list()
for index, val in enumerate(inputVal):
    if index%2 == 0:
            for x in range(1,6,2):
                resultVal = inputVal[index] + ' and ' + inputVal[x] + ' is ' + str(np.dot(resp['data'][index]['embedding'], resp['data'][x]['embedding']))
                resultList.append(resultVal)
    
pprint(resultList)

 

P.S. 

 

2022년 12월에 발표된 새 모델인 text-embedding-ada-002 를 사용하면 더 빠르고 정확하면서 비용이 더 저렴한 것 같습니다.

 

import openai
from pprint import pprint
import numpy as np

def open_file(filepath):
    with open(filepath, 'r', encoding='utf-8') as infile:
        return infile.read()

openai.api_key = open_file('openaiapikey.txt')

inputVal = ["feline friends go", "meow","canine companions say" , "woof", "bovine buddies say", "moo"]

resp = openai.Embedding.create(
    input=inputVal,
    model="text-embedding-ada-002")
    #model="text-similarity-ada-001")
    #model="text-similarity-davinci-001")
    
resultList = list()
for index, val in enumerate(inputVal):
    if index%2 == 0:
            for x in range(1,6,2):
                resultVal = inputVal[index] + ' and ' + inputVal[x] + ' is ' + str(np.dot(resp['data'][index]['embedding'], resp['data'][x]['embedding']))
                resultList.append(resultVal)
    
pprint(resultList)

 

위 코드를 사용하면 아래와 같은 결과를 얻게 됩니다.

 

고양이는 meow 이고 개는 woof 그리고 소는 moo 가 가장 유사성이 높다고 나오네요.

 

제대로 원하는 답을 얻은 것 같습니다. 저렴한 모델을 사용하면서요.

 

이 새 모델에 대한 설명은 2022년 12월에 올라온 openai 블로그 글에 자세히 나와 있습니다.

https://openai.com/blog/new-and-improved-embedding-model/

 

New and Improved Embedding Model

We are excited to announce a new embedding model which is significantly more capable, cost effective, and simpler to use. The new model, text-embedding-ada-002, replaces five separate models for text search, text similarity, and code search, and outperform

openai.com

 

반응형