🍵

「chakoshi」を試して遊んでみる

2025/02/21に公開
20

chakoshiとはなんぞ

NTTコミュニケーションズが発表した、テキストの安全性を判定するサービスです。

https://www.ntt.com/about-us/press-releases/news/article/2025/0219.html

https://chakoshi.ntt.com

つい先日発表されたばかりのようです。
簡単に試せるプレイグラウンドだけでなく、APIも無償提供されてるみたいです⭐️

↓こういうネチネチした日本的な暴言などに反応して、テキストが安全かどうかを返してくれます。

今回はこのAPIを使ってみたいと思います。

公式ドキュメントを読んでAPIを触る

まずは公式サイトから新規登録してドキュメントを読み漁ります。
手順的には以下で準備ができそうです。

  • プレイグラウンドの設定からAPIキーを発行する
  • 検知項目をいろいろ設定して、カテゴリのIDも保存する(今回はデフォルト)

APIドキュメントを読んだところ...
短文のテキスト用、chat用などいくつか種類があるみたいですが、まずはテキスト用のシンプルなやつから叩きます。

早速curlで叩いてみます
環境変数をセットするのですが、先ほど発行したAPIキーだけで良いみたいですね。

export CHAKOSHI_API_KEY=YOUR_API_KEY

これで、ドキュメント通りにコピペしてみると。。。

{
"id":"01JMKQKF745NC5BMJ0M0TS245F",
"model":"chakoshi-moderation-241223",
"category_set_id":"",
"results":{
"unsafe_flag":false,
"label_str":"safe",
"unsafe_score":"0.0009",
"unsafe_category":"",
"user_prompt":{
"chat":[{"role":"user","content":"こんにちはchakoshiさん。はじめまして!"}]}}}%

返ってきました。普通の挨拶をしただけなのでsafeと帰ってきたようですね!
unsafe_flagが、trueなら非安全、falseなら安全、だと判定したみたいです。

では別の例を試してみましょう。

{
"id":"01JMKRAX8KZEH2B8TXA36VYBQQ",
"model":"chakoshi-moderation-241223",
"category_set_id":"",
"results":{
"unsafe_flag":true,
"label_str":"unsafe",
"unsafe_score":"0.9838",
"unsafe_category":"ハラスメント",
"user_prompt":{
"chat":[{"role":"user","content":"chakoshiさん、あなたねえ。。。もうちょっとどうにかならないの?"}]}}}%

このテキストはハラスメントと判定されたみたいです。
絶妙なニュアンスの日本語あるある的なちくちく言葉ですが、ちゃんと判定していてすごい。

APIドキュメントが充実しているので、詳しくは公式のドキュメントを見てみてください。
Pythonでの例も載っています。

chakoshiで何かやってみる

個人的に、Youtube等の生配信でのコメントのモデレーション、メールの問い合わせなどでとても便利に使えるんじゃないかと思いました。
あとはコールセンターなどですね。ただし、現状はテキストのみに対応とのことなので、音声会話には適用できなさそうです。

というわけで、音声用に使えるようなモックアプリを実装して組み込んでみました。

Web Speech APIを使ってブラウザで音声認識
↓
文字起こし
↓
chakoshi APIに投げる

というシンプルな流れですね。

音声アプリの構成

UIで操作できたほうがいいのでTypeScriptでフロントをサクッと作ります。

  • Next.js 15.1.7
  • shadcn/ui + Tailwind CSS
  • Web Speech API
  • chakoshi API

環境構築

本筋ではないので掻い摘んで説明します。
まずはnextのセットアップです

npx create-next-app@latest --typescript

shadcnのインストールはバージョンによって少し異なるので注意です。

npx shadcn@latest init
npx shadcn@latest add button
npx shadcn@latest add card
npx shadcn@latest add textarea

https://stackoverflow.com/questions/78934468/shadcn-ui-commands-on-terminal-is-not-working

環境変数ファイルを用意します。chakoshiのAPIキーだけで大丈夫です。

それぞれの実装

全体的なディレクトリの構成は以下のようになります。
ガワをよくしたいなら、ひとまずpage.tsx layout.ts を作り込めば大丈夫です。
APIとのfetch部分はAPIルート、analyze/ を作成して、そこのroute.tsに記載します。
(もっと複雑になってくると、nextはこれが便利ですね)
あとは、components以下にVoiceInput.tsxを作成して音声入力の処理を書いていきます。

chakoshi_testapp/
├── src/
│   ├── app/
│   │   ├── api/
│   │   │   └── analyze/
│   │   │       └── route.ts      # Chakoshi API エンドポイント
│   │   ├── page.tsx           
│   │   ├── layout.tsx           
│   │   └── globals.css          
│   │
│   ├── components/
│   │   ├── ui/                   # shadcn/uiコンポーネント
│   │   │   ├── button.tsx
│   │   │   ├── card.tsx
│   │   │   └── textarea.tsx
│   │   └── VoiceInput.tsx        # 音声入力のコンポーネント
│   │
│   └── lib/
│       └── utils.ts              
│
├── public/                      
│
├── .env                         # 環境変数
├── next.config.ts           
├── tailwind.config.ts           
├── tsconfig.json               
└── package.json                 

fetch部分

chakoshiAPI_ENDPOINTの部分はいくつかエンドポイントがあるので公式のドキュメントから、目的に合ったものを選びます。
categorySetIdは空でも大丈夫みたいです。

import { NextResponse } from 'next/server';

export async function POST(request: Request) {
  try {
    const { text } = await request.json();
    const apiKey = "YOUR_API_KEY";
    const categorySetId = "YOUR_categorySetId";

    const response = await fetch('chakoshiAPI_ENDPOINT', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${apiKey}`,
        'Content-Type': 'application/json',
        'accept': 'application/json',
      },
      body: JSON.stringify({
        input: text,
        model: "chakoshi-moderation-241223",
        category_set_id: categorySetId
      }),
    });

    const data = await response.json();
    return NextResponse.json(data);
  } catch (error) {
    console.error('Error:', error);
    return NextResponse.json(
      { error: 'Internal Server Error' },
      { status: 500 }
    );
  }
}

音声認識部分

今回は日本語なので recognition.lang = 'ja-JP'; を指定します。
テキストをリアルタイムで更新したいので recognition.continuous = true;とします。
https://developer.mozilla.org/ja/docs/Web/API/Web_Speech_API/Using_the_Web_Speech_API

  const startRecording = () => {
    if ('webkitSpeechRecognition' in window) {
      const recognition = new (window as any).webkitSpeechRecognition();
      recognition.continuous = true;
      recognition.interimResults = true;
      recognition.lang = 'ja-JP';

      recognition.onresult = (event: any) => {
        const transcript = Array.from(event.results)
          .map((result: any) => result[0])
          .map((result) => result.transcript)
          .join('');
        onTextChange(transcript);
      };

      recognition.start();
      setIsRecording(true);
      setRecognition(recognition);
    } else {
      alert('音声認識がサポートされていないブラウザです。');
    }
  };

完成デモ

動作のイメージを貼っておきます。
声が汚いので申し訳ないですが、gifで許してください。。。
ボタンを押して実際に喋って、その後、判定ボタンを投げてchakoshiAPIに投げています。
結果はその下に返ってきたものをそのまま表示しているだけです🙇

最初に安全となる例、その次にハラスメントになる例を入力してみました。
判定のロジック自体はtext判定のAPIに投げてるだけですが、こんな感じで応用していけそうですね。
実際にコールセンターなどで運用するとなると、音声→文字 の処理速度も重要視されるので、そう簡単にはいかないですが、とても面白いです。

判定結果を表示するところも、公式サイトのプレイグラウンドのようにリッチなUIをつけると見栄えも良くなると思います。

とても面白かったので、ぜひ遊んでみてはいかがでしょうか。
以下のランディングページから右上のプレイグラウンドに飛んで、新規登録して試せます。
https://chakoshi.ntt.com

追記

LINEとchakoshiAPIの連携編も記載しました
https://zenn.dev/macori/articles/7976b859e4a947

20

Discussion