LLM 에 프롬프트를 '잘 넣는 법' 한 가지를 소개합니다.
LLM을 이용해 원하는 작업 (ex : 질의응답, 추천, 번역) 등을 하기 위해서 프롬프트로 명령을 줄 수 있고,
챗봇 형식을 이용하면 해당 작업을 시킬 수 있는데요,
Ollama 에서 OpenAI compatibility를 지원하게 되어, 즉 OpenAI 와 호환이 가능해져
이번 포스팅에서 소개합니다.
가장 먼저 ollama 홈페이지에 방문하여 ollama 를 설치합니다.
https://ollama.com/
ollama 에서 사용할 모델을 pull 합니다.
저는 Llama3 을 pull 했습니다.
ollama pull llama3
다음은 Ollama 공식 블로그에서 제공하는 Ollama 와 OpenAI Chat Completions API 호환 코드입니다.
from openai import OpenAI
client = OpenAI(
# base_url 은 ollama 의 로컬 주소로, 아래와 같이 입력합니다.
base_url = 'http://localhost:11434/v1',
api_key='ollama', # required, but unused (필수이지만 실제 사용되지는 않음)
)
# Completions API
# OpenAI 의 주요 API 중 하나로, 주어진 입력에 대해 자연어 생성(NLG) 를 수행합니다.
예를 들어, 텍스트 프롬프트가 주어지면 모델은 이를 기반으로 자연스러운 텍스트를 생성합니다.
# Chat Completions API (대화 완성 API) 는 사용자가 입력한 텍스트를 기반으로 자연스러운 대화를 생성하고 응답을 제공합니다.
response = client.chat.completions.create(
model="llama3",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Who won the world series in 2020?"},
{"role": "assistant", "content": "The LA Dodgers won in 2020."},
{"role": "user", "content": "Where was it played?"}
]
)
print(response.choices[0].message.content)
Output
The 2020 World Series was played at Globe Life Field in Arlington, Texas, and at Dodger Stadium in Los Angeles, California. The series was played in a neutral site format due to the COVID-19 pandemic, with Games 1 and 2 held at Globe Life Field and Games 3, 4, and 7 held at Dodger Stadium.
챗봇만을 구현한다면 위 Output 처럼 string 즉 text 형태여도 무방하지만
LLM을 이용하는 서비스를 개발한다면 json 포맷으로 출력을 받은 뒤에
json 포맷의 key 로부터 value 값을 가져와서 써야 합니다.
LLM의 출력이 json 포맷으로 나올 수 있도록 작업해 보겠습니다.
가장 간단한 방법으로, response format 을 json 으로 지정하는 방법이 있습니다.
from openai import OpenAI
client = OpenAI(
base_url = 'http://localhost:11434/v1',
api_key='ollama',
)
response = client.chat.completions.create(
model="llama3",
# 응답 포맷을 json 객체로 지정
response_format={ "type": "json_object" },
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Who won the world series in 2020?"},
{"role": "assistant", "content": "The LA Dodgers won in 2020."},
{"role": "user", "content": "Where was it played?"}
]
)
print(response.choices[0].message.content)
Output
❯ python llama3_test_openai.py
{}
❯ python llama3_test_openai.py
{}
❯ python llama3_test_openai.py
{}
출력 결과가 잘 나오지 않네요.
이번에는 Prompt 를 이용해 Output format 을 JSON 으로 지정하는 코드를 추가합니다.
from openai import OpenAI
client = OpenAI(
base_url = 'http://localhost:11434/v1',
api_key='ollama', # required, but unused
)
# 출력이 지정된 json format 으로 나오도록 프롬프트를 지정합니다.
command = f'''
YOU MUST STRICTLY ADHERE TO THE GIVEN FORMAT.
format your response so that is follows a JSON format, for example:
//
{{
"location": "Globe Life Field", "city": "Arlington"
}}
your response should only contain the JSON format and nothing else.
'''
response = client.chat.completions.create(
model="llama3",
response_format={ "type": "json_object" },
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Who won the world series in 2020?"},
{"role": "assistant", "content": "The LA Dodgers won in 2020."},
{"role": "user", "content": "Where was it played?"},
{"role": "user", "content": f"{command}"}
]
)
print(response.choices[0].message.content)
Output
❯ python llama3_test_openai.py
{
"location": "Globe Life Field", "city": "Arlington", "state": "Texas" }
출력은 Json 처럼 생겼지만 실제로는 개행문자(\n) 등이 포함된 온전한 json 객체 포맷은 아닙니다.
from openai import OpenAI
import json
client = OpenAI(
base_url = 'http://localhost:11434/v1',
api_key='ollama', # required, but unused
)
command = f'''
YOU MUST STRICTLY ADHERE TO THE GIVEN FORMAT.
format your response so that is follows a JSON format, for example:
//
{{
"location": "Globe Life Field", "city": "Arlington"
}}
your response should only contain the JSON format and nothing else.
'''
response = client.chat.completions.create(
model="llama3",
response_format={ "type": "json_object" },
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Who won the world series in 2020?"},
{"role": "assistant", "content": "The LA Dodgers won in 2020."},
{"role": "user", "content": "Where was it played?"},
{"role": "user", "content": f"{command}"}
]
)
# string 을 json format 으로 변환
result = json.loads(response.choices[0].message.content)
print(result)
Output
❯ python llama3_test_openai.py
{'location': 'Globe Life Field', 'city': 'Arlington', 'state': 'Texas'}
출력이 Json format 으로 잘 나오는 것을 확인했으니 위 코드를 사용하기 쉽게 함수로 변환합니다.
from openai import OpenAI
import json
client = OpenAI(
base_url = 'http://localhost:11434/v1',
api_key='ollama', # required, but unused
)
def chatbot(question:str):
command = f'''
YOU MUST STRICTLY ADHERE TO THE GIVEN FORMAT.
format your response so that is follows a JSON format, for example:
//
{{
"location": "Globe Life Field", "city": "Arlington"
}}
your response should only contain the JSON format and nothing else.
'''
response = client.chat.completions.create(
model="llama3",
response_format={ "type": "json_object" },
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": f"{question}"},
{"role": "user", "content": f"{command}"}
]
)
result = json.loads(response.choices[0].message.content)
return result
question = "Where was the world series in 2020 played?"
print(chatbot(question))
Output
❯ python llama3_test_openai.py
{'location': 'Globe Life Field', 'city': 'Arlington', 'state': 'Texas'}
❯ python llama3_test_openai.py
{'location': 'Globe Life Field', 'city': 'Arlington', 'state': 'Texas'}
❯ python llama3_test_openai.py
{'location': 'Globe Life Field', 'city': 'Arlington', 'state': 'Texas'}
'virus' 라는 키워드를 주고, 연관된 키워드들을 추천받는 추가 예제 코드입니다.
import openai
from typing import List
import json
llama_client = openai.OpenAI(
# All of your local models are automatically served on localhost:11434
base_url = "http://localhost:11434/v1",
api_key='ollama'
)
def make_prompt(keyword:str) -> List:
command = f'''
I need you to generate related a given keyword based on the following information:
given keyword: "{keyword}"
YOU MUST STRICTLY ADHERE TO THE GIVEN FORMAT.
DO NOT INCLUDE ANY KEYWORDS OTHER THAN THE GIVEN KEYWORD.
format your response so that is follows a JSON format, for example:
//
{{
"virus" : ["corona", "death", "influenza"]
}}
your response should only contain the JSON format and nothing else.
'''
prompt = [
{"role": "system", "content": "You are an advanced language model designed to generate related keywords based on a given keyword. Your task is to analyze the given keyword and produce a list of related words or phrases. Ensure that the related words are relevant and commonly associated with the given keyword."},
{"role": "user", "content": f"Please generate a list of related keywords for the following word: \"{keyword}\""},
{"role": "user", "content": f"{command}"}
]
return prompt
# https://platform.openai.com/docs/guides/text-generation/json-mode
def inference(account: openai.OpenAI, model: str, prompt: str) -> str:
response = account.chat.completions.create(
model = model,
response_format={"type": "json_object"},
temperature = 0.2,
messages = prompt,
)
return response.choices[0].message.content
def recommend_keywords(keyword:str) -> str:
result = inference(llama_client, "llama3", make_prompt(keyword))
json_data = json.loads(result)
return json_data
print(recommend_keywords('virus'))
https://ollama.com/blog/openai-compatibility
https://fornewchallenge.tistory.com/entry/Ollama-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8-%EC%9D%B4%EC%A0%9C-OpenAI-API%EB%A5%BC-%EB%AC%B4%EB%A3%8C%EB%A1%9C-%EC%A6%90%EA%B8%B0%EC%84%B8%EC%9A%94
https://ollama.com/blog/tool-support
OpenAI compatibility 수정되어서 남깁니다