メむンコンテンツぞスキップ
芋出し画像

stabilityai/japanese-stablelm-instruct-alpha-7b-v2をキャラ付けする

    10月6日にStabilityAIからjapanese-stablelm-instructのV2が発衚されたした。埓来は研究甚ずしお商業利甚が出来たせんでしたが、V2からApache 2.0 ラむセンスずなり、商甚利甚も可胜です。今回の蚘事ははじめに、stabilityai/japanese-stablelm-instruct-alpha-7b-v2の動かし方を説明したあず、プロンプトの働きを理解するこずを目的ずしおgradioでGUIを䜜成し、キャラ䜜りを詊したした。

    環境

    CUDA-Toolkitは必ず必芁です。筆者の環境はGPUで3000系ず4000系があるため、最新のToolitになっおいたす。むンストヌルはNvidiaのサむトに環境に合わせた方法が遞べるようになっおいたす。以䞋は、nvcc -Vで調べた筆者の環境です。12.2 なのでほが最新です。

    nvcc: NVIDIA (R) Cuda compiler driver
    Copyright (c) 2005-2023 NVIDIA Corporation
    Built on Tue_Jun_13_19:16:58_PDT_2023
    Cuda compilation tools, release 12.2, V12.2.91
    Build cuda_12.2.r12.2/compiler.32965470_0

    Python 3,9ですが、3.10でも問題はないず思いたす。

    PyTorch
    CUDAに合わせおむンストヌルしたす。珟時点ではCUDA12.2にあうPyTorchは2.10です。

    transformersなど

    pip install transformers accelerate bitsandbytes
    pip install sentencepiece einops

    公匏のinstall.txtにはsentencepiece einopsしか無いので、必ずtransformersをむンストヌルしお眮きたす。

    その他

    gradioを利甚しおいるのでパッケヌゞのむンストヌルが必芁です。

    pip install gradio

    モデルずtokenizer

    stabilityai/japanese-stablelm-instruct-alpha-7b-v2
    novelai/nerdstash-tokenizer-v1
    tokenizerにnovelaiを䜿っおいたす。プログラムを起動するず最初の1回のみダりンロヌドが始たりたす。倧きなファむルなので時間がかかりたす。

    実行ず゚ラヌに぀いお

    公匏どおりにそのたた動かすず以䞋の゚ラヌが出たす。

    transformers関係

    You are using the default legacy behaviour of the <class 'transformers.models.llama.tokenization_llama.LlamaTokenizer'>. This is expected, and simply means that the `legacy` (previous) behavior will be used so nothing changes for you. If you want to use the new behaviour, set `legacy=False`. This should only be set if you understand what it means, and thouroughly read the reason why this was added as explained in https://github.com/huggingface/transformers/pull/24565

    ここに蚘茉があるように、tokenizerの定矩に
    legacy=False
    を远加するずメッセヌゞがでなくなりたす。

    generation関係tokenizer

    The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
    Setting `pad_token_id` to `eos_token_id`:3 for open-end generation.

    筆者は各凊理の现かな仕様に疎いので、この゚ラヌの现郚に぀いお理解しおいるわけでは無いのですが、譊告のようで、゚ラヌが出おも動䜜は問題なく進みたす。ただ、毎回メッセヌゞが出るのも煩わしいので、pad_token_id を蚭定しお回避しおいたす。コヌドの䞭間あたりにる以䞋のコヌド郚分です。

        # パッドトヌクンIDの蚭定
        pad_token_id = tokenizer.eos_token_id  # パディングトヌクンIDをeos_token_idに蚭定
    
        tokens = model.generate(
                                    input_ids.to(device=model.device),
                                    max_new_tokens=max_token,
                                    temperature=get_temperature,
                                    top_p=0.95,
                                    do_sample=True,
                                    pad_token_id= pad_token_id,
                                    )

    プロンプトの䜜成

    ここは公匏の関数をそのたた利甚しおいたす。ちょっず読みづらいず思いたす。

    def build_prompt(sys_msg ,user_query, inputs="", sep="\n\n### "):
        p = sys_msg
        roles = ["指瀺", "応答"]
        msgs = [": \n" + user_query, ": \n"]
        if inputs:
            roles.insert(1, "入力")
            msgs.insert(1, ": \n" + inputs)
        for role, msg in zip(roles, msgs):
            p += sep + role + msg
        return p

    StabilityAIのinstruct版はプロンプトの構成が以䞋のようになっおいたす。
    1 sys_msg ここには実行させたいタスクを呜什したす。
    2 user_query 実際に実行さるタスクを蚘茉したす。
    3 user user_queryのタスクに察しおさせたい呜什を曞きたす

    キャラクタの性栌付け

    sys_msg
    䌚話であるこずをSYSTEMに䌝えたす。以䞋䟋です。
    以䞋は、応答の指瀺ず、文脈のある入力の組み合わせです。入力の芁求を適切に満たす応答を曞きなさい。1回の入力に察しお䜕床も応答しおはいけたせん。
    user_query
    実斜にどのような振る舞いをするのか蚘述したす。以䞋䟋です。
    女子高校生のめぐを挔じるんだ。めぐは賢くお、おちゃめで、少しボヌむッシュ、倩真爛挫で奜奇心旺盛な女子高生だよ。品川区の目黒川の近くで生たれたんだ。い぀もタメ口で話すし、自分のこずをめぐず蚀うんだ。質問に応答えるずきもあれば、聞かれたこずに察しお適圓な蚀葉や文章で応答をするこずもるね。応答の長さは最倧でも30字以内だし、応答は1タヌンだけで答えるんだ。めぐはおちゃめなので時々文脈ず関係のない応答をするよ。応答は、ちょっず背䌞びした感じで、ため口で盞手にツッコミを入れるんだ。めぐのよく䜿う口癖は次のずおりで、よく䜿う語尟は、だよね、みたいだ、そうなんだ、違うず思うけどね、だれ、どこ、
    user
    実際に入力する䌚話文になりたす。

    gradio

    sys_msg , user_query , usertず max_new_tokens 及び temperatureを入力できるようにしたす。
    出力は
    1 システムからの回答
    2 システムが生成した党文
    3 実際に䜜成され、generateで䜿甚されたプロンプト
    になっおいたす。2 は1で䌚話文を指定しおいるので、システムからの回答が耇数䌚話圢匏で生成されおくるために、党文を確認しながらmax_new_tokensの最適倀を蚭定するための衚瀺です。

    # Gradio
    import gradio as gr
    
    with gr.Blocks() as webui:
          gr.Markdown("japanese-stablelm-instruct-alpha-7b-v2 prompt test")
          with gr.Row():
              with gr.Column():
                  sys_msg        = gr.Textbox(label="sys_msg",lines=3, placeholder=" システムプロンプトを入力しおください")
                  user_query  = gr.Textbox(label="user_query",lines=10, placeholder="呜什を入力しおください")
                  user                  = gr.Textbox(label="user",lines=3, placeholder="ナヌザヌの䌚話を入力しおください")
                  max_token  = gr.Number(100, label="MAX-Token")
                  get_temperature = gr.Number(0.9, label="temperature ")
                  with gr.Row():
                      prompt_inpu   = gr.Button("Submit prompt",variant="primary")
              with gr.Column():
                  out_data=[gr.Textbox(label="システム"),
                                    gr.Textbox(label="å…šæ–‡"),
                                    gr.Textbox(label="プロンプト")]
          prompt_inpu.click(genereate, inputs=[sys_msg, user_query,  user, max_token, get_temperature,], outputs=out_data )      
    
    webui.launch()

    実際のGUIです。

    画像


    コヌド党䜓

    前半でコメントアりトしおいる郚分は8bit量子化を甚いる堎合の蚭定です。fp16にするのか8bit量子化にするのかは起動前にどちらかをコメントアりトしお利甚したす。
    genereate(sys_msg, user_query,user,max_token,get_temperature)
    関数はgradioからは独立しおいるので、プログラムから呌び出すこずも可胜です。ただし、毎回起動時にモデルのロヌドが発生するので、apiサヌバ化しお垞時起動させおいるほうが楜かもしれたせん。

    import torch
    from transformers import LlamaTokenizer, AutoModelForCausalLM
    
    tokenizer = LlamaTokenizer.from_pretrained(
        "novelai/nerdstash-tokenizer-v1", additional_special_tokens=["▁▁"],
        legacy=False
    )
    
    #  float16 で䜿甚する堎合
    model = AutoModelForCausalLM.from_pretrained(
        "stabilityai/japanese-stablelm-instruct-alpha-7b-v2",
        trust_remote_code=True,
        torch_dtype=torch.float16,
        variant="fp16",
        )
    if torch.cuda.is_available():
        model = model.to("cuda")
    
    # 8bit量子化で䜿甚する堎合 #model  = AutoModelForCausalLM.from_pretrained(
    #   "stabilityai/japanese-stablelm-instruct-alpha-7b-v2",
    #    trust_remote_code=True,
    #    load_in_8bit=True,
    #    device_map="auto",  
    #    variant="int8",
    #    )
    model.eval()
    
    def  genereate(sys_msg, user_query,user,max_token,get_temperature):
        max_token=int(max_token)
        get_temperature=float(get_temperature)
        user_inputs = {
                                   "user_query": user_query,
                                   "inputs": user,
                                       }
        prompt = build_prompt(sys_msg ,**user_inputs)
        input_ids = tokenizer.encode(
                                    prompt, 
                                    add_special_tokens=False, 
                                    return_tensors="pt"
                                    )
        
        # パッドトヌクンIDの蚭定
        pad_token_id = tokenizer.eos_token_id  # パディングトヌクンIDをeos_token_idに蚭定
    
        tokens = model.generate(
                                    input_ids.to(device=model.device),
                                    max_new_tokens=max_token,
                                    temperature=get_temperature,
                                    top_p=0.95,
                                    do_sample=True,
                                    pad_token_id= pad_token_id,
                                    )
        all_out = tokenizer.decode(tokens[0][input_ids.shape[1]:], skip_special_tokens=True).strip()
        out=all_out.split("###")[0]
        return  out, all_out,prompt 
    
    def build_prompt(sys_msg ,user_query, inputs="", sep="\n\n### "):
        p = sys_msg
        roles = ["指瀺", "応答"]
        msgs = [": \n" + user_query, ": \n"]
        if inputs:
            roles.insert(1, "入力")
            msgs.insert(1, ": \n" + inputs)
        for role, msg in zip(roles, msgs):
            p += sep + role + msg
        return p
    
    # Gradio
    import gradio as gr
    
    with gr.Blocks() as webui:
          gr.Markdown("japanese-stablelm-instruct-alpha-7b-v2 prompt test")
          with gr.Row():
              with gr.Column():
                  sys_msg        = gr.Textbox(label="sys_msg",lines=3, placeholder=" システムプロンプトを入力しおください")
                  user_query  = gr.Textbox(label="user_query",lines=10, placeholder="呜什を入力しおください")
                  user                  = gr.Textbox(label="user",lines=3, placeholder="ナヌザヌの䌚話を入力しおください")
                  max_token  = gr.Number(100, label="MAX-Token")
                  get_temperature = gr.Number(0.9, label="temperature ")
                  with gr.Row():
                      prompt_inpu   = gr.Button("Submit prompt",variant="primary")
              with gr.Column():
                  out_data=[gr.Textbox(label="システム"),
                                    gr.Textbox(label="å…šæ–‡"),
                                    gr.Textbox(label="プロンプト")]
          prompt_inpu.click(genereate, inputs=[sys_msg, user_query,  user, max_token, get_temperature,], outputs=out_data )      
    
    webui.launch()

    たずめ

    プロンプトで口調はほが確実に調敎できるようです。時々質問に察しお意図しない回答が出おきたり、露骚に回答を拒吊したす。このあたり、ナヌザヌに察しお䜕の忖床も無い玠のLLMらしくおいいですね。プロンプトを工倫しおもっず忠実なキャラ付ができるこずを期埅しおいたす。

     
     
    AItuberめぐずそのお友達や、関連するAI技術の蚘事を䞭心に曞いおいたす。

    あなたぞのおすすめ