# Threads セマンティック検索 API

`GET /post/semantic-search` は、文字どおりのキーワードではなく「意味」で投稿を探します。探したいテーマを一文で説明すると、直近 30 日間で意味が最も近い投稿を返します。

## セマンティック検索とキーワード検索の使い分け

たとえば「上司に不満があり、会社を辞めたい会社員」の投稿を探したいとします。`/post/search` では、離職、辭職、慣老闆、遣散（いずれも退職・辞職・ブラック上司・解雇を意味する中国語）……といったキーワードを自分で列挙する必要があります。いくら挙げてもきりがなく、そもそもこうした語を使っていない投稿も多くあります。セマンティック検索なら、次の一文（「上司に腹が立って会社を辞めたくなった会社員」という意味）だけで済みます。

> 上班族被老闆氣到想離職

結果には、「提離職」（退職を切り出した）、「辭職」（辞職）、「被通知遣散」（解雇を通告された）と書かれた投稿に加え、こうした語にはまったく触れず、上司への不満を書いているだけの投稿も含まれます。

逆に、ブランド名、アカウント、キャンペーンのハッシュタグ、製品の型番など、**明確な語**を探す場合は `/post/search` を使ってください。セマンティック検索は 1〜2 文字のキーワードに対しては精度がかなり落ちます（下記のスコアの説明を参照）。

| シナリオ | おすすめ |
| --- | --- |
| テーマはわかっているが、キーワードを漏れなく挙げられない | セマンティック検索 |
| 特定の状況や気持ちを表した投稿を探したい | セマンティック検索 |
| ブランド名、アカウント、特定の語句をモニタリングしたい | `/post/search` |
| 30 日より前のデータが必要 | `/post/search` |
| 返信も含めたい | `/post/search` |

## クイックスタート

```bash
curl -G 'https://premium-api.throk.ai/post/semantic-search' \
  -H 'Authorization: Bearer sk-throk-...' \
  --data-urlencode 'query=新手第一次去健身房不知道要練什麼' \
  --data-urlencode 'size=10'
```

レスポンス（抜粋）：

```json
{
  "results": [
    {
      "post": {
        "url": "https://threads.com/post/DaXXXXXX",
        "caption": "健身新手要怎麼練 怎麼吃 那麼多器械要怎麼選 求大佬指教",
        "like_count": 12,
        "reply_count": 3,
        "post_timestamp": 1784402170
      },
      "user": { "username": "...", "full_name": "..." },
      "score": 0.990
    }
  ],
  "credits_consumed": 30
}
```

結果は関連度の高い順に並び、各結果には投稿と投稿者の完全なデータが含まれます。

## スコアの見方

各結果の `score` は、クエリと投稿の意味的な類似度で、範囲は 0〜1 です。

- **0.98 以上**：関連性が高く、そのまま使える
- **0.95〜0.98**：おおむね関連しているが、「テーマは似ているが対象が違う」結果が混ざることがある（例：子どもが眠れない話を検索すると、ペット〈毛小孩〉が眠れない話が混ざる）
- **0.95 未満**：ノイズとして扱う

意味が完結していない断片的なキーワード（例：「蛋白」だけ）は、最高スコアでも 0.92〜0.94 にとどまり、同じスコア帯に無関係な投稿も同程度のスコアで並ぶため、絞り込めません。「台南美食」（台南グルメ）のように、それ自体で完結したテーマになっている語なら問題なく、0.98 以上のスコアが得られます。

:::tip
返された最高スコアが 0.96 を下回る場合、そのクエリはセマンティック検索に向いていません。`/post/search` のキーワード照合を使うほうが正確です。
:::

## クエリの書き方

「台南美食」で実際に試したところ、3 種類の書き方で結果の傾向が異なりました。

- **同じテーマのキーワード群**：`台南美食 台南小吃 台南餐廳推薦`。同じテーマの語を複数並べるとテーマが絞り込まれ、最も安定する書き方です。2〜3 個で十分です。ただし**同じ**テーマに限ります。無関係なテーマは別々に照会してください。
- **完全な文**：`去台南玩有什麼在地美食推薦`。結果が文の文脈に寄ります。この例は疑問文なので、返ってくるのも多くはおすすめを尋ねる投稿です。食レポを探したい場合は、内容を平叙文で記述してください。
- **単一のテーマ語**：`台南美食`。使えますが、ごく短い投稿や近隣都市の結果が混ざりやすくなります。

エンゲージメントの高い投稿がほしい場合は、クエリを書き換える必要はありません。`min_like_count` を組み合わせるだけで十分です。

## パラメータ

| パラメータ | 説明 | デフォルト |
| --- | --- | --- |
| `query` | 探したい内容を一文で記述。2〜200 文字 | 必須 |
| `size` | 返す件数。10〜3000 | 10 |
| `language` | 市場。[地域と言語](/ja/api/guides/regions/)を参照 | `zh` |
| `exclude_hk` | 広東語と香港式中国語の投稿を除外。`language=zh` の場合のみ有効 | `false` |
| `from_timestamp` | 開始時刻（UNIX 秒）。最大 30 日前まで遡れる | 30 日前 |
| `to_timestamp` | 終了時刻（UNIX 秒） | 現在 |
| `min_like_count` | いいね数が基準値以上の投稿のみ残す | 絞り込みなし |
| `min_reply_count` | 返信数が基準値以上の投稿のみ残す | 絞り込みなし |

`min_like_count` と `min_reply_count` は、意味的に上位にランクされた候補投稿の中で絞り込みます。そのため、しきい値を設定すると、返される件数が `size` より少なくなることがあります。しきい値を高くしすぎると（例：1000 いいね）、マイナーなテーマでは 1 件も残らないことがあります。

例：直近 1 週間で、いいねが 100 以上付いた減脂（ダイエット）の話題の投稿を探す。

```bash
curl -G 'https://premium-api.throk.ai/post/semantic-search' \
  -H 'Authorization: Bearer sk-throk-...' \
  --data-urlencode 'query=減脂期到底可以吃什麼' \
  --data-urlencode "from_timestamp=$(date -v-7d +%s)" \
  --data-urlencode 'min_like_count=100'
```

## 課金

最初の 10 件で合計 30 クレジット、以降 1 件ごとに 2 クレジット追加されます（例：30 件返された場合は 70 クレジット）。10 件を超える分は実際に返された件数で課金されますが、絞り込みの結果 10 件未満、あるいは 0 件になった場合でも、1 回の呼び出しにつき最低 30 クレジットがかかります。

## MCP で使う

MCP のツール名は `semantic_search_posts` です。パラメータは同じですが、`size` の上限は 10 です。

`get_inspiration` との違い：`get_inspiration` は高エンゲージメントの厳選投稿だけを検索します。`semantic_search_posts` は最近のすべての投稿を検索するため、一般の小規模アカウントの投稿も見つかります。

## 制限事項

- **検索対象は直近 30 日のみです。** それより前の投稿は `/post/search` を使ってください。
- **通常の投稿のみが対象で、返信は含みません。** 短すぎる投稿も対象外です。
- **特定の語句を含む結果は保証されません。** 厳密な照合が必要な場合は `/post/search` を使ってください。
- **地名を限定したクエリ**（例：「台北美食」）は、他の都市の結果が混ざりやすくなります。これは現在のセマンティックモデルの既知の弱点です。