見出し画像

Gradioの`ChatInterface`こと始め その4:Ollama-python編

Ollamaを用いたスクリプトを試してみました。

今回はシンプルにollama pythonライブラリーを使ってみます。

以下がサンプル例(streaming)

import ollama

stream = ollama.chat(
    model='llama2',
    messages=[{'role': 'user', 'content': 'Why is the sky blue?'}],
    stream=True,
)

for chunk in stream:
  print(chunk['message']['content'], end='', flush=True)

これをGradioのChatInterfaceの例に当てはめてみます。

上記記載のサンプルが以下です。今回は、特に、ストリーミングを表示する部分を参考にします。

import gradio as gr
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, StoppingCriteria, StoppingCriteriaList, TextIteratorStreamer
from threading import Thread

tokenizer = AutoTokenizer.from_pretrained("togethercomputer/RedPajama-INCITE-Chat-3B-v1")
model = AutoModelForCausalLM.from_pretrained("togethercomputer/RedPajama-INCITE-Chat-3B-v1", torch_dtype=torch.float16)
model = model.to('cuda:0')

class StopOnTokens(StoppingCriteria):
    def __call__(self, input_ids: torch.LongTensor, scores: torch.FloatTensor, **kwargs) -> bool:
        stop_ids = [29, 0]
        for stop_id in stop_ids:
            if input_ids[0][-1] == stop_id:
                return True
        return False

def predict(message, history):
    history_transformer_format = history + [[message, ""]]
    stop = StopOnTokens()

    messages = "".join(["".join(["\n<human>:"+item[0], "\n<bot>:"+item[1]])
                for item in history_transformer_format])

    model_inputs = tokenizer([messages], return_tensors="pt").to("cuda")
    streamer = TextIteratorStreamer(tokenizer, timeout=10., skip_prompt=True, skip_special_tokens=True)
    generate_kwargs = dict(
        model_inputs,
        streamer=streamer,
        max_new_tokens=1024,
        do_sample=True,
        top_p=0.95,
        top_k=1000,
        temperature=1.0,
        num_beams=1,
        stopping_criteria=StoppingCriteriaList([stop])
        )
    t = Thread(target=model.generate, kwargs=generate_kwargs)
    t.start()

    partial_message = ""
    for new_token in streamer:
        if new_token != '<':
            partial_message += new_token
            yield partial_message

gr.ChatInterface(predict).launch()

とりあえず、雛形として以下ができて動きました。
モデルは、dolphin-mistral に変えています。


import gradio as gr
import ollama


def predict(message, history):
    prompt = [{'role': 'user', 'content': message}]
    print("prompt:", prompt)


    stream = ollama.chat(
        model='dolphin-mistral',
        messages=prompt,
        stream=True,
    )

    partial_message = ""
    for chunk in stream:
        new_token = (chunk['message']['content'])
        partial_message += new_token
        yield partial_message


gr.ChatInterface(predict).launch()

ただこれだと、一問一答で会話を覚えていません。
過去に自分が書いた記事を読み返してみると、履歴を全部プロンプトとして放り込むので良さそうです。

ということで、以下でOKとなりました。

import gradio as gr
import ollama


def predict(message, history):
    prompt = []

    for human, assistant in history:
        prompt.append({'role': 'user', 'content': human})
        prompt.append({'role': 'assistant', 'content': assistant})
        
    prompt.append({'role': 'user', 'content': message})
    #print  (f"履歴の形はこんな感じ:\n {history}")
    #print  (f"promptの形はこんな感じ:\n {prompt}")


    stream = ollama.chat(
        model='dolphin-mistral',
        messages=prompt,
        stream=True,
    )

    partial_message = ""
    for chunk in stream:
        new_token = (chunk['message']['content'])
        partial_message += new_token
        yield partial_message


gr.ChatInterface(predict).launch()

あと、このモジュールだけだと、どうも他のパラメーターは設定できないようなので、Ollamaに登録しているいくつかのモデルだけは選択できるようにしてみました。

下は、とりあえず自分のOllamaにいれてある3つをmodelとして選択して、引き渡すようにしたスクリプトです。

import gradio as gr
import ollama


def predict(message, history, model):
    prompt = []

    for human, assistant in history:
        prompt.append({'role': 'user', 'content': human})
        prompt.append({'role': 'assistant', 'content': assistant})
        
    prompt.append({'role': 'user', 'content': message})
    #print  (f"履歴の形はこんな感じ:\n {history}")
    #print  (f"promptの形はこんな感じ:\n {prompt}")


    stream = ollama.chat(
        model=model,
        messages=prompt,
        stream=True,
    )

    partial_message = ""
    for chunk in stream:
        new_token = (chunk['message']['content'])
        partial_message += new_token
        yield partial_message


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 mode, Default is olphin-mistral."),]
    )


if __name__ == "__main__":
    demo.queue().launch()

蛇足:Stabel-Beluga:70Bはやっぱりいい感じの生成してくれるという印象です。


#AI #AIとやってみた #やってみた #Gradio #Huggingface #大規模言語モデル #ローカルLLM

この記事を最後までご覧いただき、ありがとうございます!もしも私の活動を応援していただけるなら、大変嬉しく思います。