ローカルで ChatGPT API を使って動かす環境がほしかったので作ったメモ
gradio の component で chat のインターフェイスが簡単に作れるのでとても簡単に作れてしまった
role とは
role は input として使うテキストに付与される情報のこと
種類としては
system/assistant/user
system は事前に与える役割や制約を入 れるもの
引用をままはるが、役割を content の最初の文に書き、
instructions 部分に制約を記載するなどを行う
Instructions:{"role": "system", "content": "Assistant is an intelligent chatbot designed to help users answer their tax related questions.
- 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 をクリックしてリセットしてチャットをやり直すこともできる