uni memo

ChatGPT with gradio

ChatGPT with gradio

ローカルで ChatGPT API を使って動かす環境がほしかったので作ったメモ

gradio の component で chat のインターフェイスが簡単に作れるのでとても簡単に作れてしまった

role とは

role は input として使うテキストに付与される情報のこと

種類としては

system/assistant/user
がある

system は事前に与える役割や制約を入れるもの

引用をままはるが、役割を content の最初の文に書き、

instructions 部分に制約を記載するなどを行う

{"role": "system", "content": "Assistant is an intelligent chatbot designed to help users answer their tax related questions.
Instructions:

  • Only answer questions related to taxes.
  • If you’re unsure of an answer, you can say “I don’t know” or “I’m not sure” and recommend users go to the IRS website for more information. ”
    }
    ,

{"role": "user", "content": "When are my taxes due?"}

ref.

動作環境

  • python 3.11
  • gradio 3.25
  • openai 0.27
  • pydantic 1.10

コード実行、動作

pip install gradio openai pydantic
  • コード app.py

from typing import List, Union

import openai
import gradio as gr
from pydantic import BaseModel

SYSTEM_PROMPT = """
あなたはプロのギタリストです。音楽や作曲に対する質問に答えてください
"""

MODEL = "gpt-3.5-turbo"
# MODEL = "gpt-4"

class Message(BaseModel):
    role: str
    content: str

def openai_create(
        messages: List[Message],
        tempareture: float,
        openai_api_key: str,
        ) -> str:
    openai.api_key = openai_api_key
    response = openai.ChatCompletion.create(
        model=MODEL,
        messages=[m.dict() for m in messages],
        temperature=tempareture,
        max_tokens=400,
        top_p=1,
        frequency_penalty=0,
        presence_penalty=0.6,
    )

    return response.choices[0]["message"]["content"]

def chatgpt_clone(
        input: str,
        messages: list[Message],
        tempareture: float,
        openai_api_key: str,
        ) -> Union[List[tuple[str, str]], List[Message]]:
    init = Message(role="system", content=SYSTEM_PROMPT)
    messages = messages or [init]

    m = Message(role="user", content=input)
    messages.append(m)

    res = openai_create(messages, tempareture, openai_api_key)
    messages.append(Message(role="assistant", content=res))
    # tuple で履歴をテキストボックスに送る必要がある
    history = [(messages[i].content, messages[i + 1].content) for i in range(1, len(messages) - 1, 2)]
    return history, messages

def main():
    with gr.Blocks() as block:
        with gr.Row():
            openai_api_key_textbox = gr.Textbox(
                label="api key",
                placeholder="OpenAI API key を入力(sk-...) ↵️",
                lines=1,
                type="password"
            )
            temperature = gr.Number(label="temperature", placeholder="set tempareture", value=0.9)

        gr.Markdown("""
        let's talk
        """)
        chatbot = gr.Chatbot(label="chat")
        message = gr.Textbox(placeholder="input message", label="message")
        state = gr.State()

        with gr.Row():
            submit = gr.Button("submit")
            clear = gr.Button("clear")
        submit.click(chatgpt_clone,
                     inputs=[message, state, temperature, openai_api_key_textbox],
                     outputs=[chatbot, state]
                     )
        clear.click(lambda: [], None, chatbot)
        clear.click(lambda: [], None, state)

        block.launch(server_name="0.0.0.0", debug=True)

if __name__ == '__main__':
    main()
  • 実行例

python app.py

message を入力して送信すると ChatGPT からの返信がくる コンテキストを保持できるトークン数が限られているのでその場合は clear をクリックしてリセットしてチャットをやり直すこともできる

参考

2024, Built with Gatsby. This site uses Google Analytics.