Open7

Nextjs + Neon

Keita MitsuhashiKeita Mitsuhashi

.envとapp/sctions.tsを設定

// app/actions.ts
"use server";
import { neon } from "@neondatabase/serverless";

export async function getData() {
    const sql = neon(process.env.DATABASE_URL);
    const data = await sql`...`;
    return data;
}
Keita MitsuhashiKeita Mitsuhashi

テーブルの初期化はNeonの管理画面上のSQLエディターからSQLを実行。
開いた時にサンプルがあるので、とりあえずそれを実行。
結果タブが見やすい。

Keita MitsuhashiKeita Mitsuhashi

チャットの履歴を保存したいので、テーブルを作る。今回はアプリ画面で出す用ではなくて管理目的のみなので簡易的になりそう。

  • sender ... AIかユーザーか
  • value ... チャットの内容
  • system_prompt_version ... システムプロンプトのバージョンコード (運用上管理されている)
  • thread_id ... フロントから発行する
  • create_at ... タイムスタンプ
CREATE TABLE IF NOT EXISTS chat_history(
  id SERIAL PRIMARY KEY,
  sender TEXT NOT NULL,
  value TEXT NOT NULL,
  thread_id TEXT NOT NULL,
  system_prompt_version TEXT NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Keita MitsuhashiKeita Mitsuhashi

actions.tsに関数を追加

export async function saveHistyroy(props: {
  sender: string;
  value: string;
  thread_id: string;
}) {
  if (!process.env.DATABASE_URL) {
    throw new Error("DATABASE_URL is not set");
  }
  const sql = neon(process.env.DATABASE_URL);
  const data =
    await sql`INSERT INTO chat_history (sender, value, thread_id, system_prompt_version)
VALUES (${props.sender}, ${props.value}, ${props.thread_id}, '2');`;
  return data;
}

ページからコールする。

export default function Home() {
  ...
  const {
    messages,
    setMessages,
    input,
    setInput,
    handleInputChange,
    handleSubmit,
    isLoading,
  } = useChat({
    onFinish: (message) => handleFinishMessage(message),
  });

  const handleFinishMessage = (latestMessage: Message) => {
    saveHistyroy({
      sender: latestMessage.role,
      value: latestMessage.content,
      thread_id: threadId.current,
    });
  };
  ...
}
Keita MitsuhashiKeita Mitsuhashi

今回のはユーザー識別やスレッド表示を考慮してないが、綱領した上であるあるテーブルは用意しておけそう。