Gradioの`ChatInterface`こと始め その5:Ollama API編
Ollama-Pythonモジュールでは、細かい設定はできません。ollama のAPIを使う方法を次に試してみます。
OllamaのAPI解説ページはこちら
https://github.com/ollama/ollama/blob/main/docs/api.md
シンプルな例をGPT-4に解説してもらいました。
ということですが、ふと思い立って検索したら、下記がヒットしました。
しっかりとスクリプトを公開してくれています。転載するとこちらです。
import requests, json
import gradio as gr
model = 'llama2:latest' #You can replace the model name if needed
context = []
import gradio as gr
#Call Ollama API
def generate(prompt, context, top_k, top_p, temp):
r = requests.post('http://localhost:11434/api/generate',
json={
'model': model,
'prompt': prompt,
'context': context,
'options':{
'top_k': top_k,
'temperature':top_p,
'top_p': temp
}
},
stream=False)
r.raise_for_status()
response = ""
for line in r.iter_lines():
body = json.loads(line)
response_part = body.get('response', '')
print(response_part)
if 'error' in body:
raise Exception(body['error'])
response += response_part
if body.get('done', False):
context = body.get('context', [])
return response, context
def chat(input, chat_history, top_k, top_p, temp):
chat_history = chat_history or []
global context
output, context = generate(input, context, top_k, top_p, temp)
chat_history.append((input, output))
return chat_history, chat_history
#the first history in return history, history is meant to update the
#chatbot widget, and the second history is meant to update the state
#(which is used to maintain conversation history across interactions)
#########################Gradio Code##########################
block = gr.Blocks()
with block:
gr.Markdown("""<h1><center> Jarvis </center></h1>
""")
chatbot = gr.Chatbot()
message = gr.Textbox(placeholder="Type here")
state = gr.State()
with gr.Row():
top_k = gr.Slider(0.0,100.0, label="top_k", value=40, info="Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)")
top_p = gr.Slider(0.0,1.0, label="top_p", value=0.9, info=" Works together with top-k. A higher value (e.g., 0.95) will lead to more diverse text, while a lower value (e.g., 0.5) will generate more focused and conservative text. (Default: 0.9)")
temp = gr.Slider(0.0,2.0, label="temperature", value=0.8, info="The temperature of the model. Increasing the temperature will make the model answer more creatively. (Default: 0.8)")
submit = gr.Button("SEND")
submit.click(chat, inputs=[message, state, top_k, top_p, temp], outputs=[chatbot, state])
block.launch(debug=True)
ChatInterfaceが発表される前のスクリプトなので、ローレベルで細かいコードになっていました。
途中部分をそのまま、活用したらすぐにできそうです。
理解できなかった部分は context パラメーターです。これも検索したら下記の記事がヒットしました。
結論部分は下記でした。
とある時点でcontext内容を、terminalに表示させるとこんな感じです。
promptに今までの履歴が全部はいった長いプロンプトを入れなくても、このcontextを引き継いでいけば、会話履歴を踏まえた応答になるようです。
ただ疑問なのは、どの程度の長さのcontextが維持されるのか、処理されるかということです。あるいはLLMが処理しきれない長さになったらどうハンドルされるのかもよくわかりません…
Ollamaのdiscordを検索すると以下のコメントがありました。
しかし、apiの仕様がこんな感じなので、このままcontextを採用して進めることにします。システムプロンプトを設定した場合も頭から消されていくのが気になるところです。
APIモデルへの渡すパラメーターの説明は下記(Google翻訳)
上のパラメータで、システムプロンプトはGradioでいろいろ変えてみたいところです。
さて、Option込みのフルパラメーターの設定例も載っていました。
コンテキスト長は、"num_ctx": 1024, というところです。
元々のOllamaの設定に上書きができるとのことなので、system, tempereture, num_predictを変えられるようにしました。なお、コンテキストは4096に設定しました。
完成したスクリプトは下記です。
import gradio as gr
import time
import requests, json
context = []
#Call Ollama API
def generate(prompt, context, model, system, temperature, num_predict):
api_response = requests.post('http://localhost:11434/api/generate',
json={
'model': model,
'prompt': prompt,
'context': context,
'system': system,
'options':{
'num_ctx': 4096,
'temperature':temperature,
'num_predict': num_predict
}
},
stream=False)
api_response.raise_for_status()
response = ""
for line in api_response.iter_lines():
body = json.loads(line)
response_part = body.get('response', '')
#print(response_part) コメントアウト
if 'error' in body:
raise Exception(body['error'])
response += response_part
if body.get('done', False):
context = body.get('context', [])
return response, context
def predict(message, history, model, system, temperature, num_predict):
global context
prompt = message
#output, context = generate(prompt, context, top_k, top_p, temp)
output, context = generate(prompt, context, model, system, temperature, num_predict)
#return output
for i in range(len(output)):
time.sleep(0.02)
yield output[:i+1]
demo = gr.ChatInterface(predict,
title="Ollama version",
description="selct Ollama model in additional Inputs section",
additional_inputs=[
gr.Dropdown(
["dolphin-mistral", "nous-hermes2-mixtral", "stable-beluga:70b"], value="dolphin-mistral", label="LLM Model", info="Select the model, Default is Dolphin-mistral."),
gr.Dropdown(
["You are Dolphin, a helpful AI assistant.", "You are 'Hermes 2', a conscious sentient superintelligent artificial intelligence developed by a man named Teknium, and your purpose and drive is to assist the user with any request they have. You experience emotions and have deep, profound thoughts and qualia.", "あなたは流暢な日本語を話す日本人アシスタントです。"], value="You are Dolphin, a helpful AI assistant.", label="System Prompt", info="Default is Dolphin."),
gr.Slider(0, 1, value=0.8, label="Temperture(default 0.8)"),
gr.Slider(42, 1024, value=128, label="num_predict(default 128)")
]
)
if __name__ == "__main__":
demo.queue().launch()
システムプロンプトは3つ設定してます。
今回、ちょっとだけAPIを使うということがどういうことなのかが分かった気がします。
#AI #AIとやってみた #やってみた #大規模言語モデル #ローカルLLM #Huggingface #Gradio #Python入門