ElasticSearch Relevance Engine (ESRE)

因為 ESRE 的出現,許多功能在 Elastic Stack 當中即可獨立完成,我們暫時不再需要 Python Client 的操作,接下來的操作步驟將透過 Kibana 進行。

6.1 使用 Kibana > Search > Machine Learning > Model Management > Trained Models 下載與佈署模型

  1. 打開 kibana

  2. 在上方搜尋框,搜尋 Machine Learning,並且點選第一個推薦的結果

  1. 進入 Machine Learning 頁面後,在左方選單中,點選 Model Management 底下的 Trained Models

  1. 點選 Add trained model

  2. 選擇 E5 模型,並點選下載。

  1. 等待下載完成。

  1. 點選 Deploy 的按鈕。

  1. Start 完成後,會出現 Deployed 的狀態。

6.2 建立 Ingest Pipeline 配合 Inference Process 使用模型進行 Embedding 處理

# 模擬執行的效果
POST _ingest/pipeline/_simulate
{
  "pipeline": {
    "processors": [
      {
        "inference": {
          "model_id": ".multilingual-e5-small_linux-x86_64",
          "input_output": [
            {
              "input_field": "overview",
              "output_field": "overview_embedding"
            }
          ]
        }
      }
    ]
  },
  "docs": [
    {
      "_source": {
        "overview": "在《閃電俠》中,貝瑞使用超能力回到過去,想要改變已發生的事件,卻衝擊了時空秩序。當貝瑞試圖拯救家人時,不小心改變了未來,使他受困於另一個時空中;在這個時空中,回歸的薩德將軍正威脅著毀滅世界,但卻沒有超級英雄可以求助,除非貝瑞能說服一位退休的蝙蝠俠重現江湖,解救一位被監禁的氪星人……儘管他可能找錯了人。到頭來,貝瑞為了拯救他所在的世界,返回他所知的未來,唯一的希望就是用盡生命賽跑,但他最後做出的犧牲足以拯救整個宇宙嗎?"
      }
    }
  ]
}

# 先查看 Movies 的 Mapping 現況
GET movies/_mapping?filter_path=**.overview*

# 正式建立 Ingest Pipeline
PUT _ingest/pipeline/movies_embedding
{
  "description": "HWDC 2024 Joe's Demo", 
  "processors": [
    {
      "inference": {
        "model_id": ".multilingual-e5-small_linux-x86_64",
        "input_output": [
          {
            "input_field": "overview",
            "output_field": "overview_embedding_v2"
          }
        ]
      }
    }
  ]
}

# 使用 Update By Query 將所有文件重新 Reindex 一遍,並套用 Ingest Pipeline 進行 Embedding 處理
POST movies/_update_by_query?pipeline=movies_embedding
{
  "query": {
    "match_all": {}
  }
}

# 先查看 Movies 的 Mapping 更新後的結果
GET movies/_mapping?filter_path=**.overview*

# 修改 movies 的 Index Settings,讓未來的資料寫入時,都會套用此 Ingest Pipeline
PUT movies/_settings
{
  "index.default_pipeline": "movies_embedding"
}

# 查看修改後的 Index Settings
GET movies/_settings

6.3 搜尋時,也能直接使用 Elasticsearch 內部的 Model,不需再 Python Client 先進行 Embedding 的處理。

# 當 Elasticsearch 裡面有這個 Embedding Model,我們 Search 時也能直接使用
GET movies/_search
{
  "_source": {
    "excludes": "overview_*"
  }, 
  "knn": {
    "field": "overview_embedding_v2",
    "k": 10,
    "num_candidates": 100,
    "query_vector_builder": {
      "text_embedding": { 
        "model_id": ".multilingual-e5-small_linux-x86_64", 
        "model_text": "低級的超級英雄" 
      }
    }
  }
}

6.4 使用外部 OpenAI 的 Text Embedding 模型

:::info 這把 API Key 供大家試用,僅提供 gpt-4o-mini & text-embedding-3-small,並且在研討會結束後就會移除。 sk-proj-(已失效,請改用自己的 API Key) 可在 Kibana Dev Tools 的 Variables 設定中,加入 openai_api_key 名稱的變數,以方便直接執行以下的範例。 :::

# 建立 Text Embedding 模型設定
PUT _inference/text_embedding/openai-embeddings-3-small
{
  "service": "openai",
  "service_settings": {
    "api_key": "${openai_api_key}",
    "model_id": "text-embedding-3-small"
  }
}

# 測試 Embedding
POST _inference/text_embedding/openai-embeddings-3-small
{
  "input": "一隻狗狗"
}

:::success 這個透過 Inference API 建立好的 text_embedding 的 model id: openai-embeddings-3-small 就如同前面 Elasticsearch 載入的模型,可直接在 Inference Processor 或是 knn 的 query_vector_build 直接使用 :::

6.5 使用外部 OpenAI 的 Completion 推論模型

# 建立 OpenAI Completion 推論模型設定 (喬叔提供的 ApiKey 只能使用 gpt-4o-mini)
PUT _inference/completion/openai-completion-gpt-4o-mini
{
  "service": "openai",
  "service_settings": {
    "api_key": "${openai_api_key}",
    "model_id": "gpt-4o-mini"
  }
}

# 測試使用 OpenAI Completion API 進行推論
POST _inference/completion/openai-completion-gpt-4o-mini
{
  "input": "OpenAI 是什麼?"
}

6.6 Ingest Pipeline 配合 OpenAI Completion 推論模型的使用

新聞摘要

POST _ingest/pipeline/_simulate
{
  "pipeline": {
    "processors": [
      {
        "script": {
          "source": """ctx._prompt = '你是一位專業的台灣新聞編輯,你的任務是將新聞內容產生50字重點摘要。新聞內容:' + ctx.content
          """
        }
      },
      {
        "inference": {
          "model_id": "openai-completion-gpt-4o-mini",
          "input_output": {
            "input_field": "_prompt",
            "output_field": "summary"
          }
        }
      },
      {
        "remove": {
          "field": "_prompt"
        }
      }
    ]
  },
  "docs": [
    {
      "_source": {
        "content": """〔記者吳昇儒、俞肇福/基隆報導〕基隆一名5個月大倪姓女嬰8月1日委由周姓保母照顧後,卻於15日發現有全身癱軟情形,送醫急救後,竟發現腦部出血,醫生研判是遭到外力劇烈搖晃導致。家屬質疑,是透過基隆市保母系統找來的周姓保母對女嬰不當對待,才會導致女嬰腦部嚴重受創,醫院目前已通報發生疑似「兒虐事件」,由檢警偵辦釐清中。
        
        基隆市政府兒童及少年事務處指出,目前已全力協助救治女嬰,並協助其家庭度過難關,將會儘快查明事件真相,該案也依規定通報衛福部社會及家庭署備案,兒少保護網絡群組也已通報基隆地檢署,由檢察官指揮基隆警二分局調查中,釐清女嬰傷勢成因。"""
      }
    },
    {
      "_source": {
        "content": """〔記者吳昇儒/新北報導〕62歲郭姓男子今日上午與友人前往新北市南子吝步道健行時,不慎在路途中摔倒導致左腳骨折,無法行走。消防局獲報後,立刻派員前往救援,約於1小時後抵達郭男所在區域,利用捲式擔架將其固定後,花2小時將他搬運下山,送醫救治後幸無生命危險。
        
        消防隊員們詢問後得知,郭男和另2名友人共同前往南子吝步道健行,走到一半突然跌倒,導致左腳骨折,已無法自行山下,才會請消防隊員前往搶救。
        
        隊員於12時27分接觸到受傷的郭男,見他左腳腫脹有骨折情形,所幸意識清楚,暫無生命危險,隨即利用捲式擔架將其固定,並將患者搬運到登山口,送往醫院急救。
        
        新北市政府消防局第六大隊大隊長羅億田表示,提醒所有喜愛登山的朋友,從事登山戶外運動應結伴同行,假設遇到危險或身體不適才能有同伴在第一時間電話求救或作緊急處置。如果不幸發生意外情況,應立即撥打119或110報案,提供正確的人事時地物等情資,才能讓救援迅速到位。"""
      }
    },
    {
      "_source": {
        "content": """〔記者林宜樟/嘉義報導〕嘉義縣警局水上分局8月13日發生曾姓通緝犯脫逃事件,闖進民宅偷走神明金牌及車輛,開往中埔鄉方向後棄車逃逸;水上分局偵查隊今天上午在彰化縣芬園鄉一處日租套房,將曾姓通緝犯逮捕,並查獲接應曾嫌的劉姓嫌犯,將2人帶回水上分局偵辦。
        
        嘉義縣水上警分局員警8月13日逮捕43歲曾姓毒品通緝犯,曾男在分局偵查隊接受筆錄時,竟趁中午吃便當解開手銬之際,從後門逃跑,並闖民宅偷走,竊取價值10萬元金飾財物,並偷走賓士車代步逃逸,之後將車子棄置在中埔鄉公館偏僻草叢逃逸無蹤,警方漏夜展開地毯式搜捕。"""
      }
    }
  ]
}

擷取電影重要關鍵字

POST _ingest/pipeline/_simulate
{
  "pipeline": {
    "processors": [
      {
        "inference": {
          "model_id": ".multilingual-e5-small_linux-x86_64",
          "input_output": [
            {
              "input_field": "overview",
              "output_field": "overview_embedding"
            }
          ]
        }
      },
      {
        "script": {
          "source": """
ctx._prompt='針對以下電影標題與內容描述,產生5~10個最能代表這部電影的關鍵字,關鍵字以|隔開,直接回覆關鍵字結果,不需要任何解釋。

電影標題: ' + ctx.title + '

電影內容:
' + ctx.overview + '

關鍵字分別為: '"""
        }
      },
      {
        "inference": {
          "model_id": "openai-completion-gpt-4o-mini",
          "input_output": [
            {
              "input_field": "_prompt",
              "output_field": "_keywords"
            }
          ]
        }
      },
      {
        "split": {
          "field": "_keywords",
          "separator": "\\|",
          "target_field": "keywords"
        }
      },      
      {
        "remove": {
          "field": "_prompt"
        }
      },      
      {
        "remove": {
          "field": "_keywords"
        }
      }
    ]
  },
  "docs": [
    {
      "_source": {
          "title": "殺戮列車",
        "overview": "當一名陸軍突擊隊員發現他的真愛違背自身意願訂婚時,他登上了開往新德里的火車,大膽地試圖破壞包辦婚姻。但當一群持刀的盜賊開始恐嚇他所乘坐火車上的無辜乘客時,這名突擊隊員親自與他們對抗,展開了一場不顧生死的殺戮狂歡,以拯救周圍的人——將原本平常的通勤變成了一場充滿腎上腺素的刺激之旅。"
      }
    },
    {
      "_source": {
        "title": "陰間大法師",
        "overview": "一對溺死的年輕夫妻化為厲鬼返家,卻必須尋求一個滑稽鬼怪的幫助,嚇嚇這些魯莽無禮的新屋主。"
      }
    }
  ]
}

Last updated