🏡

小ネタ:LangChain.jsなら(GPT-4o | Claude3)が動く

2024/05/14に公開

はじめに

以前、Hono+LangChain.jsならAWS LambdaClaude3が動く。という記事を書きました。

https://zenn.dev/watany/articles/bdf0d80afd290a

5/14にGPT-4oモデルが登場!こちらも試してみたいですね。

https://openai.com/index/spring-update/

1. Claude3を動かす

上の記事を抜粋すると、このコードで動作します。

https://zenn.dev/watany/articles/bdf0d80afd290a#code

コード
index.tsx
import { Hono } from "hono";
import { handle } from "hono/aws-lambda";
import { logger } from "hono/logger";

import { HumanMessage } from "@langchain/core/messages";
import { BedrockChat } from "@langchain/community/chat_models/bedrock";

const app = new Hono();
app.use(logger());

const Layout = (props: any) => (
  <html>
    <head>
      <meta charset="UTF-8" />
      <title>{props.title}</title>
    </head>
    <body>{props.children}</body>
  </html>
);

app.get("/", (c) => {
  return c.render(
    <Layout title="Image Analysis">
      <h1>Image Analysis</h1>
      <form action="/analyze" method="post" enctype="multipart/form-data">
        <input type="file" name="image" accept="image/*" required />
        <button type="submit">Analyze</button>
      </form>
    </Layout>,
  );
});

app.post("/analyze", async (c) => {
  const body = await c.req.parseBody();
  const image = body["image"];

  if (!image || Array.isArray(image) || typeof image === "string") {
    return c.text("No image uploaded or invalid image", 400);
  }

  const imageData = await image.arrayBuffer();
  const imageUrl = `data:${image.type};base64,${Buffer.from(imageData).toString("base64")}`;

  const model = new BedrockChat({
    model: "anthropic.claude-3-sonnet-20240229-v1:0",
    region: "us-east-1",
  });

  const message = new HumanMessage({
    content: [
      { type: "text", text: "What's in this image?" },
      { type: "image_url", image_url: { url: imageUrl } },
    ],
  });

  const res = await model.invoke([message]);
  const analysis = res.content;

  return c.render(
    <Layout title="Image Analysis Result">
      <h1>Image Analysis Result</h1>
      <img src={imageUrl} alt="Uploaded Image" />
      <p>{analysis}</p>
      <a href="/">Analyze another image</a>
    </Layout>,
  );
});

export const handler = handle(app);

Haiku, Opusでそれぞれ例の画像を説明してもらった(結果をGoogle翻訳をかけている)様子です。

2. GPT-4oを動かす

LangChain公式ドキュメントにまだ乗っていないのですが、Twitter(X)にはこのようにあるので、参考に変えてみる。

https://twitter.com/LangChainAI/status/1790089006455398583

// import { BedrockChat } from "@langchain/community/chat_models/bedrock";
import { ChatOpenAI } from "@langchain/openai";
// const model = new BedrockChat({
//  model: "anthropic.claude-3-opus-20240229-v1:0",
//  region: "us-west-2",
//  });
const model = new ChatOpenAI({
    model: "gpt-4o",
    apiKey: c.env.OpenAIKey
});

Langchainで抽象化されているので、実装としてはModel部分を変更するだけでうまくいきます。

まとめ

OpenAI一強時代においてはLangChainの魅力を個人的には感じていなかったのですが、このように複数のモデルがしのぎを削りあう局面における抽象化層として、採用するのはありですね。

LangChainを使うことで、ローカルLLM+Ollamaとも交換できるのが良さそう。

https://js.langchain.com/v0.1/docs/integrations/llms/ollama/

依存ライブラリが多めなのとLangChain自体のアプデ対応をどうするか、というのが悩みどころかな。

Discussion