コンテンツにスキップ

テキストの悪用を検出

テキスト虐待検出APIは、テキスト内の虐待(禁止用語、スパム広告)を検出し、検証するAPIです。

準備

Hive コンソール > AI サービス > 悪用検出 > チャット悪用検出 メニューにアクセスできるか確認し、できない場合は、Hive コンソールの権限管理ガイドを参照してメニューアクセス権を取得してください。チャット悪用検出に新しいプロジェクトを登録します。

テキストが攻撃的かどうかの判断

テキストを送信した後、それがスパム広告であるか、禁止された単語を含んでいるかを判断し、結果を返します。

リクエストURL

ライブURL https://tads.withhive.com/cads2/send-text-data
サンドボックスURL https://sandbox-tads.withhive.com/cads2/send-text-data
HTTPメソッド POST
コンテンツタイプ application/json

リクエストボディ

フィールド名 説明 タイプ 必須
project_key プロジェクトキー 文字列 Y
text_log テキスト情報 オブジェクト Y

テキストログ

フィールド名 説明 タイプ 必須
text_array テキストとテキストが送信された時間を含むオブジェクトの配列 配列(オブジェクト) Y
text_count text_array内のオブジェクトの数 整数 Y

テキスト配列のオブジェクト

フィールド名 説明 タイプ 必須
time_stamp テキストが送信された時間(UTCベースのISO形式の時間文字列、例: 2024-01-30T10:35:49.95457+09:00 文字列 Y
text_info JSONオブジェクトから取得したHive コンソールの暗号化キーを使用してAES256で暗号化された文字列。最大サイズは5KBです。暗号化方法の詳細については、例のコードを参照してください。 文字列 Y

text_info JSONオブジェクト

以下のフォーマットに従ってJSONオブジェクトを作成し、それをAES256で暗号化してtext_info文字列を形成します。

フィールド名 説明 タイプ 必須
user_id ユーザーのユニークID番号 文字列 Y
lang_code 言語コード (ISO 639-1)
* 韓国語: ko
* 英語: en
* 日本語: ja
* 簡体字中国語: zh-hans
* 繁体字中国語: zh-hant
* スペイン語: es
* ロシア語: ru
* ドイツ語: de
* フランス語: fr
* ポルトガル語: pt
* イタリア語: it
* タイ語: th
* インドネシア語: id
* トルコ語: tr
* マレー語: ms
* ベトナム語: vi
文字列 Y
text 検査するテキスト 文字列 Y
text_type テキストがチャットテキストの場合、以下の3つのチャット形式のいずれかに該当します。
* "chat_party": パーティーチャット
* "chat_guild": ギルドチャット
* "chat_whisper": ウィスパー
文字列 N
room_num テキストがチャットテキストの場合、これはチャットルーム番号です。 文字列 N
channel_info テキストがチャットテキストの場合、これはチャットチャンネル情報です。 文字列 N

応答

フィールド名 説明 タイプ
result_code レスポンスコード 文字列
result_text レスポンスコードの説明 文字列
result_array 検出結果を含む配列 配列(オブジェクト)

結果配列

フィールド名 説明 タイプ
tads_result 検出結果 オブジェクト
text_result 元のテキストと検出結果に基づいてマスキングを適用した結果 オブジェクト

tads_result

フィールド名 説明 タイプ
forbidden_yn 禁止ワードが検出されたかどうか(0: テキストに禁止ワードは見つかりませんでした、1: テキストに禁止ワードが見つかりました) 文字列
spam_yn テキストがスパムとして検出されたかどうか(0: スパムとして検出されていません、1: スパムとして検出されました) 文字列
aug_yn テキストがバッチ処理されたかどうか(0: バッチ処理されていません、1: バッチ処理されました) 文字列
long_yn テキストが長い文字列かどうか、つまり5,000文字を超える場合、検出アルゴリズムをテキストに対して実行できないことを意味します(0: 5,000文字未満、1: 5,000文字以上) 文字列
テキスト結果
フィールド名 説明 タイプ
text 検出するためのテキスト 文字列
masking_text マスキングが適用されたテキスト(Hive コンソールでマスキング設定が行われていない場合、またはtads_result.forbidden_ynの値が0の場合、textは同一になります) 文字列

レスポンスコード

コード テキスト 備考
200 "成功" 成功
500 "不正なリクエスト" リクエストにエラーがあります。リクエストURLとリクエストボディが正しいか確認してください。
501 "不正なデータカウント" 渡されたテキストのカウントが一致しません。text_countの値とtext_arrayの長さが一致する必要があります。
502 "不正な秘密鍵" 秘密鍵の値が不正です。プロジェクト管理でプロジェクトの秘密鍵を確認してください。
503 "未登録のプロジェクトキー" プロジェクトキーの値が不正です。プロジェクト管理でプロジェクトのプロジェクトキーを確認してください。
506 "システムエラー" これはネットワークエラーなどの内部エラーです。しばらくしてからAPIを再度呼び出してください。
507 "メッセージのサイズが大きすぎます" テキストのサイズが大きすぎます。text_arrayの最大サイズは5KBです。メッセージのサイズを減らしてください。

リクエストの例

import json
import base64
import requests
from datetime import datetime
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad

def encrypt(text, user_id, lang_code, secret_key, channel_info=None, room_num=None, text_type=None) -> str: ## 暗号化のためのコード
    aes = AES.new(secret_key, AES.MODE_ECB)
    jsonData =  {"text_type": text_type, ## 必要な場合のみ使用
                "room_num" : room_num, ## 必要な場合のみ使用
                "user_id": user_id,
                "channel_info" : channel_info, ## 必要な場合のみ使用
                "lang_code": lang_code,
                "text": text}
    rawJsonStr = json.dumps(jsonData)
    paddedStr = pad(rawJsonStr.encode("utf-8"),AES.block_size)
    encrypted_data = aes.encrypt(paddedStr)
    encrypted_data_b64 = base64.b64encode(encrypted_data).decode("utf-8")
    return encrypted_data_b64

project_key = <PROJECT_KEY>
secret_key = <SECRET_KEY>
now = datetime.now().astimezone().isoformat()
lang_code = "ko"
user_id = "432414"
channel_info = "4342314" ## Use it only when it is required
room_num = "12312" ## Use it only when it is required
text_type = "chat_whisper" ## Use it only when it is required
url = "https://tads.withhive.com/cads2/send-text-data"

payload =  {"project_key": project_key,
                      "text_log": {
                              "text_count": 2, ## should match the number of elements of text_array
                              "text_array": [
                                            {"time_stamp": now,
                                            "text_info": encrypt(text=str("test1"), 
                                                            user_id=user_id,
                                                            channel_info=channel_info, ## Use it only when it is required
                                                            room_num=room_num, ## Use it only when it is required
                                                            text_type=text_type, ## Use it only when it is required
                                                            lang_code=lang_code,
                                                            secret_key=secret_key)},
                                            {"time_stamp": now,
                                            "text_info": encrypt(text=str("test2"), 
                                                            user_id=user_id,
                                                            channel_info=channel_info, ## Use it only when it is required
                                                            room_num=room_num, ## Use it only when it is required
                                                            text_type=text_type, ## Use it only when it is required
                                                            lang_code=lang_code,
                                                            secret_key=secret_key)}]},}

res = requests.post(url, data=json.dumps(payload), headers={"Content-Type": "application/json"})
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

import java.util.Base64;
import org.jooq.tools.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.extern.slf4j.log;

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

@Slf4j
public class TadsComponent {

@Autowired
RestTemplate restTemplate;

@Autowired
ObjectMapper objectMapper;


public void sendHttp() throws Exception{
    String projectKey =  <PROJECT_KEY>; // プロジェクトキーを提供してください
    String secretKey =  <SECRET_KEY>;  // プロジェクトの秘密鍵を提供してください

    String url = "https://tads.withhive.com/cads2/send-text-data";
    String user_id = "432414";
    String channel_info = "4342314"; // 必要な場合のみ使用
    String room_num = "12312"; // 必要な場合のみ使用
    String text_type = "chat_whisper"; // 必要な場合のみ使用
    String lang_code = "ko";
    String text_1 = "test1";
    String text_2 = "test2";

    DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
    ZonedDateTime now = ZonedDateTime.now();

    Map<String, Object> payload = new HashMap<>();
    payload.put("project_key", projectKey);

    Map<String, Object> textLog = new HashMap<>();
    textLog.put("text_count", 2); // should match the number of elements of text_array

    Map<String, Object> textArray1 = new HashMap<>();
    textArray1.put("time_stamp", now.format(formatter));
    textArray1.put("text_info", encrypt(text_1, user_id, channel_info, room_num, text_type, lang_code, secretKey));


Map<String, Object> textArray2 = new HashMap<>();
   textArray2.put("time_stamp", now.format(formatter));
   textArray2.put("text_info", encrypt(text_2, user_id, channel_info, room_num, text_type, lang_code, secretKey));

    Object[] textArrayObj = {textArray1, textArray2};
    textLog.put("text_array", textArrayObj);
    payload.put("text_log", textLog);
    JsonNode callBodyNode = objectMapper.valueToTree(payload);
    HttpHeaders headers = new HttpHeaders();
    headers.add("Content-Type", "application/json");
    HttpEntity<String> entity = new HttpEntity<>(callBodyNode.toString(), headers);
    ResponseEntity<String> responseEntity =  restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
    int responseStatusCode =  responseEntity.getStatusCodeValue();
    String responseBodyString = responseEntity.getBody();
    JsonNode responseBodyNode = objectMapper.readTree(responseBodyString);
    return;
}

public static String encrypt(String text, String UserId, String channelInfo, String roomNum, String textType, String langCode, String secretKey) {
    try {
        Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding");
        SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), "AES");
        aes.init(Cipher.ENCRYPT_MODE, secretKeySpec);
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("room_num", roomNum); // Use it only when it is required
        map.put("channel_info", channelInfo); // Use it only when it is required
        map.put("lang_code", langCode);
        map.put("text", text);
        map.put("text_type", textType); // Use it only when it is required
        map.put("user_id", UserId);
        String encrypt_str = JSONObject.toJSONString(map);
        byte[] paddedData = padString(encrypt_str).getBytes();
        byte[] encryptedData = aes.doFinal(paddedData);
        return Base64.getEncoder().encodeToString(encryptedData);
    } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
        e.printStackTrace();
        return null;
    }
}
private static String padString(String source) {
    char paddingChar = ' ';
    int size = 16;
    int x = source.length() % size;
    int padLength = size - x;
    StringBuilder paddedString = new StringBuilder(source);
    for (int i = 0; i < padLength; i++) {
        paddedString.append(paddingChar);
    }
    return paddedString.toString();
}} // 暗号化のためのコード

応答の例

{
    "result": {
        "result_array": '[
                        {"tads_result":{
                            "forbidden_yn":"0",
                            "spam_yn":"0",
                            "aug_yn":"0",
                            "long_yn":"0"},
                        "text_result":{
                            "text":"test1",
                            "masking_text":"test1"
                        }},
                        {"tads_result":{
                            "forbidden_yn":"0",
                            "spam_yn":"0",
                            "aug_yn":"0",
                            "long_yn":"0"},
                        "text_result":{
                            "text":"test2",
                            "masking_text":"test2"
                        }}
                            ]',
        "result_code": "200",
        "result_text": "success"
    }
}