見出し画像

最新のjapanese-stablelm-3b-4e1t-instructとjapanese-stablelm-instruct-gamma-7bを試してAPI化とキャラ付け

japanese-stablelm-3b-4e1t-instructとjapanese-stablelm-instruct-gamma-7b及びその他のスタンダード版が本日公開されました。早速動かしましたので報告とAPI化も出来てしまったので記事にしました。

環境

これまでの記事と同じです。

公式コード

当然動きます。今回からtokenizerが変更になっています。

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM

tokenizer = AutoTokenizer.from_pretrained("stabilityai/japanese-stablelm-3b-4e1t-instruct")
model = AutoModelForCausalLM.from_pretrained(
  "stabilityai/japanese-stablelm-3b-4e1t-instruct",
  trust_remote_code=True,
  torch_dtype="auto",
)
model.eval()

if torch.cuda.is_available():
    model = model.to("cuda")

def build_prompt(user_query, inputs="", sep="\n\n### "):
    sys_msg = "以下は、タスクを説明する指示と、文脈のある入力の組み合わせです。要求を適切に満たす応答を書きなさい。"
    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

# Infer with prompt without any additional input
user_inputs = {
    "user_query": "与えられたことわざの意味を小学生でも分かるように教えてください。",
    "inputs": "情けは人のためならず"
}
prompt = build_prompt(**user_inputs)

input_ids = tokenizer.encode(
    prompt, 
    add_special_tokens=False, 
    return_tensors="pt"
)

tokens = model.generate(
    input_ids.to(device=model.device),
    max_new_tokens=256,
    temperature=1,
    top_p=0.95,
    do_sample=True,
)

out = tokenizer.decode(tokens[0][input_ids.shape[1]:], skip_special_tokens=True).strip()
print(out)

7Bモデルに変更するには、tokenizer部分を書き換えます。

tokenizer = AutoTokenizer.from_pretrained("stabilityai/japanese-stablelm-instruct-gamma-7b")
model = AutoModelForCausalLM.from_pretrained(
  "stabilityai/japanese-stablelm-instruct-gamma-7b",
  torch_dtype="auto",
)

APIサーバ化とキャラ設定

これ、実は簡単で、この記事の前の記事のモデルを変えるだけです。プロンプトの構成が同じなので、tokenizerとmodelを変更すればすぐに動きました。違いは以下の部分のみです。このコードはstabilityai/japanese-stablelm-3b-4e1t-instructのときの例です。

tokenizer = AutoTokenizer.from_pretrained("stabilityai/japanese-stablelm-3b-4e1t-instruct")

model = AutoModelForCausalLM.from_pretrained(
  "stabilityai/japanese-stablelm-3b-4e1t-instruct",
    trust_remote_code=True,
  torch_dtype="auto",
)

サーバの全コード

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
from fastapi import FastAPI,Form
from fastapi.responses import HTMLResponse
from pydantic import BaseModel

tokenizer = AutoTokenizer.from_pretrained("stabilityai/japanese-stablelm-3b-4e1t-instruct")

model = AutoModelForCausalLM.from_pretrained(
  "stabilityai/japanese-stablelm-3b-4e1t-instruct",
    trust_remote_code=True,
  torch_dtype="auto",
)
model.eval()
if torch.cuda.is_available():
    model = model.to("cuda")

model.eval()

app = FastAPI()

# rootエンドポイント
@app.get("/", response_class=HTMLResponse)
async def get_root(request):
    return templates.TemplateResponse("index.html", {"request": request})

class AnswerRequest(BaseModel):
     sys_msg : str
     user_query:str
     user:str
     max_token:int
     temperature:float 

@app.post("/generate/")
def  genereate(gen_request: AnswerRequest):
    sys_msg       =gen_request.sys_msg
    user_query =gen_request.user_query
    user                 =gen_request.user
    max_token =gen_request.max_token
    get_temperature=gen_request.temperature

    user_inputs = {
                               "user_query": user_query,
                               "inputs": user,
                                   }
    prompt = build_prompt(sys_msg ,**user_inputs)
    print("prompt =",prompt )
    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()
    print("SYS_OUT=", all_out)
    out=all_out.split("###")[0]
    result=200
    return {'message':result, "out":out,"all_out":all_out}

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

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8005)

gradio−GUIによるキャラ作り

こちらも以下の記事でtokenizerとmodelを変更すればすぐに動きました。ソースコードは省略します。APIサーバと同様にtokenizerとmodel部分を変更してください。

これまでの様子

japanese-stablelm-3b-4e1t-instructがstabilityai/japanese-stablelm-instruct-alpha-7b-v2と同程度かなという感想です。ただ、質問に関係の無い回とをするケースは多いようです。プロンプトの工夫が必要なんでしょうね。

stabilityai/japanese-stablelm-instruct-alpha-7b-v2でGUI化のプロンプトテス環境やAPIサーバ化をやっていたので最新のモデルの評価がいち早く出来ました。ちょっとラッキーですね。