- Published on
Ollama Parameters Setting
- Authors
- Name
- hongreat
- ✉️hongreat95@gmail.com
ChatGPT 가 완전 대중화되면서 OPENAI의 API를 기반으로 한 예제가 많은데, Ollama와 같은 로컬친화적인 LLM에 대한 UseCase가 아직 많지 않습니다.
LLM을 비롯한 AI에서 파라미터 조절은 다양한 상황에 AI를 사용하기 위한 필수 작업입니다.
Ollama 를 Langchain의 LLM으로 사용하면서 파라미터 조절하는 방법과 그에 해당하는 세팅을 Bind 하는 방법을 기록합니다.
Ollama parameter
Ollama 는 기본적으로 Modelfile 이라는 파일기반의 세팅을 지원(문서의 표현을 빌리면 Blueprint; 청사진, 설계도)합니다.
이 세팅 값을 통해서 model 자체를 build 할때 편하게 커스텀 할 수도있고, 문서에 나와있는 parameter들을 조절해서 Langchain에서 LLM(like Ollama)을 세밀하게 조절할 수 도 있습니다.
Ollama Parameter Description
(하단 문서 참고)
자주 사용하게될 파라미터는 temperature(창의정도) 와 num_predict(토큰 수) 정도가 될 것 같습니다.
- mirostat
- 텍스트의 난해함(혼란도, perplexity)을 조절하기 위해 Mirostat 샘플링을 활성화합니다.
- 기본값: 0 (0 = 비활성화, 1 = Mirostat, 2 = Mirostat 2.0)
- 텍스트의 난해함(혼란도, perplexity)을 조절하기 위해 Mirostat 샘플링을 활성화합니다.
- mirostat_eta
- 알고리즘이 생성된 텍스트의 피드백에 얼마나 빨리 반응할지 결정합니다. 값이 낮으면 조정이 느리고, 높으면 빠릅니다.
- 기본값: 0.1
- 알고리즘이 생성된 텍스트의 피드백에 얼마나 빨리 반응할지 결정합니다. 값이 낮으면 조정이 느리고, 높으면 빠릅니다.
- mirostat_tau
- 출력 텍스트의 일관성과 다양성 사이의 균형을 조절합니다. 값이 낮을수록 더 집중적이고 일관된 텍스트를 생성합니다.
- 기본값: 5.0
- 출력 텍스트의 일관성과 다양성 사이의 균형을 조절합니다. 값이 낮을수록 더 집중적이고 일관된 텍스트를 생성합니다.
- num_ctx
- 다음 토큰을 생성할 때 사용할 문맥 창의 크기를 설정합니다.
- 기본값: 2048
- 다음 토큰을 생성할 때 사용할 문맥 창의 크기를 설정합니다.
- num_gqa
- 트랜스포머 레이어에서 사용할 GQA 그룹 수를 설정합니다. 특정 모델에 필요합니다. (
llama2:70b
모델에서는 8로 설정.)- 기본값: 1
- 트랜스포머 레이어에서 사용할 GQA 그룹 수를 설정합니다. 특정 모델에 필요합니다. (
- num_gpu
- GPU에 보낼 레이어 수를 설정합니다. macOS에서는 기본값이 1로 설정되어 메탈 지원이 활성화됩니다. 0으로 설정하면 비활성화됩니다.
- 기본값: 50
- GPU에 보낼 레이어 수를 설정합니다. macOS에서는 기본값이 1로 설정되어 메탈 지원이 활성화됩니다. 0으로 설정하면 비활성화됩니다.
- num_thread
- 계산에 사용할 스레드 수를 설정합니다. 기본적으로 Ollama가 시스템의 물리적 CPU 코어 수를 감지하여 최적 성능을 설정합니다.
- 기본값: 8
- 계산에 사용할 스레드 수를 설정합니다. 기본적으로 Ollama가 시스템의 물리적 CPU 코어 수를 감지하여 최적 성능을 설정합니다.
- repeat_last_n
- 반복을 방지하기 위해 모델이 얼마큼 과거로 돌아가서 문맥을 참조할지 설정합니다.
- 기본값: 64 (0 = 비활성화, -1 =
num_ctx
와 동일)
- 기본값: 64 (0 = 비활성화, -1 =
- 반복을 방지하기 위해 모델이 얼마큼 과거로 돌아가서 문맥을 참조할지 설정합니다.
- repeat_penalty
- 반복되는 단어를 얼마나 강하게 억제할지 설정합니다. 값이 높을수록 반복을 더 강하게 억제합니다.
- 기본값: 1.1
- 반복되는 단어를 얼마나 강하게 억제할지 설정합니다. 값이 높을수록 반복을 더 강하게 억제합니다.
- 💫temperature
- 모델의 창의성을 조절합니다. 값이 높을수록 더 창의적이고 예측 불가능한 응답이 나옵니다.
- 기본값: 0.8
- seed
- 텍스트 생성에 사용할 난수 시드를 설정합니다. 특정 숫자를 설정하면 같은 프롬프트에서 항상 같은 결과를 생성합니다.
- 기본값: 0
- stop
- 특정 패턴을 만나면 텍스트 생성을 멈추게 할 정지 시퀀스를 설정합니다. 여러 개의 정지 패턴을 지정할 수 있습니다.
- 기본값: "AI assistant:"
- tfs_z
- 확률이 낮은 토큰의 영향을 줄이기 위해 사용되는 Tail Free 샘플링을 설정합니다. 값이 높을수록 낮은 확률의 토큰을 더 줄입니다.
- 기본값: 1
- 💫num_predict
- 텍스트 생성 시 예측할 최대 토큰 수를 설정합니다.
- 기본값: 128 (-1 = 무한 생성, -2 = 문맥을 모두 채움)
- top_k
- 무의미한 텍스트 생성을 줄이기 위한 설정입니다.
- 값이 높을수록 더 다양한 응답을 생성하며, 값이 낮을수록 더 보수적인 응답을 생성합니다.
- 기본값: 40
- 무의미한 텍스트 생성을 줄이기 위한 설정입니다.
- top_p
top-k
와 함께 작동하여, 값이 높을수록 더 다양한 텍스트를 생성하고, 값이 낮을수록 더 집중적이고 보수적인 텍스트를 생성합니다.- 기본값: 0.9
실험
parameter 값이 잘 적용되는지 확인하기 위해, 간단한 invoke 구문을 3개정도 돌려봤습니다.
import time
from langchain_community.llms.ollama import Ollama
from langchain.prompts import PromptTemplate
def test_llm_parameter(parameter):
print("start")
start_time = time.time()
print(f"세팅 시작 및 파라미터 : {parameter}")
llm = Ollama(model="llama2:latest", **parameter)
prompt = PromptTemplate.from_template("What is {input}?")
print("Chain running")
chain = prompt | llm
response = chain.invoke({"input": "AI"})
end_time = time.time()
duration = end_time - start_time
print(f"execution time: {duration:.2f}s")
return response
# 파라미터 리스트
params_list = [
{
"mirostat": 2,
"temperature": 1.2,
"num_predict": 50,
},
{
"mirostat": 1,
"temperature": 0.2,
"num_predict": 100,
},
{"top_k": 10, "top_p": 0.5, "repeat_penalty": 1.8, "num_predict": 50},
]
for idx, params in enumerate(params_list):
print("*" * 50, f"{idx+1}번째 시도", "*" * 50)
print(test_llm_parameter(params))
모델에 상관없이 역시나 실행시간과 극적인 차이점을 보인 것은 토큰 수와 난해함의 정도 였습니다.
- num_predict 를 50 / 100 으로 두고했을 때
- 난해하거나 보수적인 정도를 낮췄을 때
이런 경우 속도가 훨씬 간결한 모습입니다.
Setting Bind
LLM 에 대한 세팅 값을 call 한 시점과 상관없이 세팅하거나, 여러개의 chain 을 둘때 유용한 메서드인 것 같습니다.
from langchain_community.llms.ollama import Ollama
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages(
[
("system", "This system is professional on IT."),
("user", "{user_input}"),
]
)
model = Ollama(model="llama2:latest")
messages = prompt.format_messages(user_input="what is python language?")
before_answer = model.invoke(messages)
print("binding 이전 출력", before_answer)
chain = prompt | model.bind(num_predict=10)
after_answer = chain.invoke({"user_input": "what is python language?"})
print("binding 이후 출력", after_answer)
출력 결과는 다음과 같이 잘 적용된 모습을 볼 수 있습니다.
- 토큰 수에 대한 정의는 모델에 따라 매우 상이하기 때문에, 토큰 수가 디테일하게 필요한 경우 get_token();pseudocode 같은 메서드는 필수로 작성 해야 합니다.
- 모델별로 파라미터가 다르고, 사용&적용하는 방법 또한 매우 다릅니다.
- 이는 곧, 하나의 모델에 익숙해져도 다른 모델을 사용하게 되는 경우 새로운 실험과 기록이 필요하다는 것을 의미합니다.
- 잘 만들어진 여러 모델에 대한 특성들을 기록하는 것도 하나의 재미요소로 볼 수 있을 것 같습니다.
- OPENAI 가 확실히 빠르고 좋긴하지만, 비용을 생각하면… Ollama 도 괜찮다고 생각합니다.