1
0

More than 1 year has passed since last update.

Discord で gpt-4

Posted at

備忘

# %%
import discord
import openai
import os
import tiktoken
import logging


def num_tokens_from_messages(messages, model="gpt-4-0314"):
    """Returns the number of tokens used by a list of messages.
    from https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb
    """
    try:
        encoding = tiktoken.encoding_for_model(model)
    except KeyError:
        print("Warning: model not found. Using cl100k_base encoding.")
        encoding = tiktoken.get_encoding("cl100k_base")
    if model == "gpt-3.5-turbo":
        print("Warning: gpt-3.5-turbo may change over time. Returning num tokens assuming gpt-3.5-turbo-0301.")
        return num_tokens_from_messages(messages, model="gpt-3.5-turbo-0301")
    elif model == "gpt-4":
        print(
            "Warning: gpt-4 may change over time. Returning num tokens assuming gpt-4-0314.")
        return num_tokens_from_messages(messages, model="gpt-4-0314")
    elif model == "gpt-3.5-turbo-0301":
        # every message follows <|start|>{role/name}\n{content}<|end|>\n
        tokens_per_message = 4
        tokens_per_name = -1  # if there's a name, the role is omitted
    elif model == "gpt-4-0314":
        tokens_per_message = 3
        tokens_per_name = 1
    else:
        raise NotImplementedError(
            f"""num_tokens_from_messages() is not implemented for model {model}. See https://github.com/openai/openai-python/blob/main/chatml.md for information on how messages are converted to tokens.""")
    num_tokens = 0
    for message in messages:
        num_tokens += tokens_per_message
        for key, value in message.items():
            num_tokens += len(encoding.encode(value))
            if key == "name":
                num_tokens += tokens_per_name
    num_tokens += 3  # every reply is primed with <|start|>assistant<|message|>
    return num_tokens


def cgpt(message_content, message_history):
    # 環境変数 OPENAI_API_KEY を取得して、 openai.api_key にセットする
    openai.api_key = os.environ["OPENAI_API_KEY"]

    # その他、パラメータを設定する
    MODEL_NAME = 'gpt-4'
    MAX_TOKENS = 1200  # 1回のリクエストで返ってくるトークン数の上限
    model_token_limit = {
        'gpt-4': 8192,
        'gpt-3.5-turbo': 4096,
    }

    # 入力を message_history に user として追加する
    message_history.append({"role": "user", "content": message_content})

    # message_history の token 数を数える
    num_tokens = num_tokens_from_messages(message_history)
    print(f"num_tokens before: {num_tokens}")

    # ここで num_tokens + max_tokens が model_token_limit[model_name] を超える場合は、
    # num_tokens が model_token_limit[model_name] を下回るまで、 message_history の先頭を削除する
    while num_tokens + MAX_TOKENS > model_token_limit[MODEL_NAME]:
        print(f"trimming message_history: {message_history[0]}")
        message_history = message_history[1:]
        num_tokens = num_tokens_from_messages(message_history)
        print(f"num_tokens after trimming: {num_tokens}")

    # OpenAI GPT に入力を渡す
    r = openai.ChatCompletion.create(
        model=MODEL_NAME,
        messages=message_history,
        temperature=0.9,
        max_tokens=MAX_TOKENS,
        top_p=1,
        frequency_penalty=0.5,
        presence_penalty=0.5,
    )

    # 返答を表示する
    res_text = r.choices[0].message.content

    # 返答をメッセージに追加する
    message_history.append({"role": "assistant", "content": res_text})

    # message_history の token 数を数える
    num_tokens = num_tokens_from_messages(message_history)
    print(f"num_tokens after: {num_tokens}")

    return res_text, message_history


class ChatGPTDiscord():
    def __init__(self) -> None:
        self.message_history = []

    def chatevent(self):
        # 環境変数 DISCORD_BOT_SIMPLE を取得して TOKEN にセットする
        TOKEN = os.environ["DISCORD_BOT_SIMPLE"]

        # インテントの生成
        intents = discord.Intents.default()
        intents.message_content = True

        # クライアントの生成
        client = discord.Client(intents=intents)

        # discordと接続した時に呼ばれる
        @client.event
        async def on_ready():
            print(f'We have logged in as {client.user}')

        # メッセージを受信した時に呼ばれる
        @client.event
        async def on_message(message):

            # 自分のメッセージを無効
            if message.author == client.user:
                return

            # メッセージを返す
            res_text, message_history = cgpt(
                message.content, self.message_history)
            self.message_history = message_history
            await message.channel.send(res_text)

        # クライアントの実行
        client.run(token=TOKEN, log_level=logging.ERROR)


c = ChatGPTDiscord()
c.chatevent()

point

  • できるだけ長く文脈を保つように、 token の数をちゃんと計算するようにする
  • system のところに「あなたは優秀な助手です」みたいなことを入れてたけど、 gpt-4 がすでにその使命を帯びていて意味ないのでやめた。
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0