Databricksのai_generate_text()とOpenAIを用いた顧客レビュー分析

[Analyze customer reviews with ai\_generate\_text\(\) and OpenAI \| Databricks on AWS](https://docs.databricks.com/large-language-models/ai-generate-text-example.html) [2023/6/20時点]の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

:::note info
**プレビュー**
本機能は[パブリックプレビュー](https://docs.databricks.com/release-notes/release-types.html)です。
:::

本書では、顧客レビューを検証し、レスポンスを生成する必要があるかどうかを判断するために、Databricks SQLのビルトイン関数である`ai_generate_text()`をどのように活用するのかを説明します。関数の詳細については、[AI Functions on Databricks](https://docs.databricks.com/large-language-models/ai-functions.html)をご覧ください。

このガイドのデータセットとコマンドは、Databricks demoの[Action Customer Reviews at Scale with Databricks SQL AI Functions](https://www.dbdemos.ai/demo.html?demoName=sql-ai-functions)から提供されるものです。このデモでは、eコマースウェブサイトに送信された雑貨製品の顧客レビューを真似るOpenAIによって生成されたフェイクデータを活用します。
![](https://docs.databricks.com/_images/ai-generate-text-architecture-customer-reviews.png)

このサンプルでは以下のステップを実施します:

- フリーフォームの顧客レビューテキストを構成要素のエンティティにブレークダウン。
- エンティティごとに感情を特定し、顧客にレスポンスすべきかどうかを判定。
- お客様を満足させるであろう代替製品を説明するレスポンスの生成。

![](https://docs.databricks.com/_images/ai-generate-text-data-flow.png)

# 前提条件

- このガイドのコマンドを実行したい場合には、実行対象のデータセットが必要となります。[Generate Fake data with AI Functions](https://www.dbdemos.ai/demo-notebooks.html?demoName=sql-ai-functions)ノートブックでフェイクデータセットを作成することができます。
- このガイドのSQLコマンドは、Databricks SQLクエリーエディタで実行される必要があります。インタラクティブクラスターを用いてDatabricksノートブックで直接実行することはできません。
- `ai_generate_text()`関数は、proあるいはサーバレスSQLウェアハウスのパブリックプレビューでのみ利用できます。
    - このパブリックプレビューに参加するには、[AI Functions Public Preview enrollment form](https://docs.google.com/forms/d/e/1FAIpQLScVyh5eRioqGwuUVxj9JOiKBAo0-FWi7L3f4QWsKeyldqEw8w/viewform)を提出してください。
- [Azure OpenAI key](https://learn.microsoft.com/azure/cognitive-services/openai/overview#how-do-i-get-access-to-azure-openai)
- キーを[Databricks secrets](https://docs.databricks.com/security/secrets/index.html)に格納。このサンプルでは、*スコープ*`tokens`、*シークレット*`azure-openai`にAPIキーを格納します。[SQLからLLMを利用できるDatabricksのai\_generate\_text\(\)のセットアップと検討事項](https://qiita.com/taka_yayoi/items/7b23e334a7b0e1e5c01c)をご覧ください。

# プロンプトデザイン

GPTモデルから有用な結果を得る際に鍵となるのは:

- 適切に構成された質問を尋ねる。
- 期待する回答のタイプに対して具体的になる。

テーブルに容易にできる形態で結果を取得するには、モデルに対して`JSON`表現を反映する文字列で結果を返却するように依頼し、期待するスキーマを指定します。

このシナリオにおけるサンプルプロンプトを以下に示します:

*A customer left a review. Follow up with anyone who appears unhappy.*

*Extract all entities mentioned. For each entity:*
- *Classify sentiment as [“POSITIVE”,”NEUTRAL”,”NEGATIVE”]*
- *Whether customer requires a follow-up: Y or N*
- *Reason for requiring followup*

*Return JSON ONLY. No other text outside the JSON.*

*JSON format:*

```json:JSON
{
"entities": [{
    "entity_name": "entity_name",
    "entity_type": "entity_type",
    "entity_sentiment": "entity_sentiment",
    "followup": "Y or N for follow up",
    "followup_reason": "reason for followup"
  }]
}
```

*Review:*

*<’insertreview_text_here’>_*

# SQL関数の作成

組織内の他のシナリオで再利用できるように、あなたの質問を細かなSQL関数に分解することをお勧めします。

このセクションを通じて、エンドユーザーから`ai_generate_text()`呼び出しの詳細を抽象化するためにSQL関数を作成し、これらの関数をAzure OpenAIとやりとりを行うインタフェースとして活用します。

## Azure OpenAIへの呼び出しの制御

以下のラッパー関数`prompt_handler()`では、Azure OpenAIへのすべての呼び出しを取り扱います。Azure OpenAIのAPIキーはDatabricksシークレットに格納され、`secret()`関数でそれを参照することができます。また、Azure OpenAIのリソース名(`resourceName`)とモデルのデプロイメント名 (`deploymentName`)を指定することができます。

```sql:SQL
CREATE OR REPLACE FUNCTION PROMPT_HANDLER(prompt STRING)
RETURNS STRING
RETURN AI_GENERATE_TEXT(prompt,
  "azure_openai/gpt-35-turbo",
  "apiKey", SECRET("tokens", "azure-openai"),
  "temperature", CAST(0.0 AS DOUBLE),
  "deploymentName", "llmbricks",
  "apiVersion", "2023-03-15-preview",
  "resourceName", "llmbricks"
);
```

## 顧客レビューデータの分析

`annotate_review()`関数は、レビューに対してエンティティ、エンティティの感情、フォローアップが必要かどうかとその理由の注釈付けを行います。プロンプトは適切にフォーマットされた`json`表現を返却するので、Deltaテーブルへのインサートのような後段でのクエリーが容易になる`struct`タイプを返却するように指示できることに注意してください。

```sql:SQL
CREATE OR REPLACE FUNCTION ANNOTATE_REVIEW(review STRING)
RETURNS STRUCT<entities: ARRAY<STRUCT<entity_name: STRING, entity_type: STRING, entity_sentiment: STRING, followup: STRING, followup_reason: STRING>>>
RETURN FROM_JSON(
  PROMPT_HANDLER(CONCAT(
    'A customer left a review. Follow up with anyone who appears unhappy.
     Extract all entities mentioned. For each entity:
      - classify sentiment as ["POSITIVE","NEUTRAL","NEGATIVE"]
      - whether customer requires a follow-up: Y or N
      - reason for requiring followup

    Return JSON ONLY. No other text outside the JSON. JSON format:
    {
        entities: [{
            "entity_name": <entity name>,
            "entity_type": <entity type>,
            "entity_sentiment": <entity sentiment>,
            "followup": <Y or N for follow up>,
            "followup_reason": <reason for followup>
        }]
    }

    Review:
    ', review)),
  "STRUCT<entities: ARRAY<STRUCT<entity_name: STRING, entity_type: STRING, entity_sentiment: STRING, followup: STRING, followup_reason: STRING>>>"
);
```

`annotate_review()`関数がどのようにフリーフォームの顧客レビューを分類するのかを確認するために、顧客レビューデータセットからデータを与えることができます。

```sql:SQL
SELECT review_body,
  ANNOTATE_REVIEW(review_body) AS review_annotated
FROM dbdemos.openai_demo.fake_reviews
WHERE product_category = "Grocery"
LIMIT 3;
```

## レコメンデーションを伴うレスポンスの生成

顧客レスポンスを確認した後で、彼らの不満に基づくレスポンスを生成し、試すべき代替製品のレコメンデーションを含めるために、`generate_response()`を活用することができます。

```sql:SQL
CREATE OR REPLACE FUNCTION GENERATE_RESPONSE(product STRING, entity STRING, reason STRING)
RETURNS STRING
RETURN PROMPT_HANDLER(
  CONCAT("What alternative products can you recommend for ", product,
    " when a customer had a complaint about ", entity, " because ", reason,
    "Give me a response in the tone of an empathetic message back to the customer; only provide the body")
);
```

以下では、Country Choice Snacking Cookiesに対する顧客レビューに対するサンプルのメッセージレスポンスを生成しています。

```sql:SQL
SELECT GENERATE_RESPONSE("Country Choice Snacking Cookies", "cookies", "Quality issue") AS customer_response
```

# アドホックのクエリー

また、新たに作成した`prompt_handler()`関数を用いてアドホッククエリーを作成することができます。

例えば、レビューが飲み物を議論している稼働かを理解することに興味を持つかもしれません。

```sql:SQL
SELECT review_id,
  PROMPT_HANDLER(
    CONCAT(
      "Does this review discuss beverages? Answer Y or N only, no explanations or notes. Review: ", review_body)
  ) AS discusses_beverages,
  review_body
FROM dbdemos.openai_demo.fake_reviews
WHERE review_id IN ("R9LEFDWWXPDEY", "R27UON10EV9FSV", "R299ZTEFIAHRQD")
ORDER BY discusses_beverages DESC;
```

### Databricksクイックスタートガイド

[Databricksクイックスタートガイド](https://www.amazon.co.jp/dp/B09V1YXFVQ/)


### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)