iT邦幫忙

2024 iThome 鐵人賽

DAY 0
0
自我挑戰組

重新開始 elasticsearch 系列 第 26

2024 鐵人賽 Day27: How to RAG - Provide Context

  • 分享至 

  • xImage
  •  

前一篇手動擷取 ES 內的電影資料提供給 LLM,今天要來透過 python 腳本自動化。

首先要做的就是把要問 LLM 的問題轉為 vector 並在 ES 搜尋相關文本,搜尋詞轉 vecotr 之前寫過了,可以直接使用:


def embedding(model_id, texts):
    # hf_token = os.getenv("HF_TOKEN")
    api_url = f"https://api-inference.huggingface.co/pipeline/feature-extraction/{model_id}"
    headers = {"Authorization": f"Bearer {hf_token}"}
    body = {"inputs": texts, "options":{"wait_for_model":True}}
    response = requests.post(api_url, headers=headers, json=body)
    if response.status_code != 200:
        print(f"Error: {response.status_code}, {response.text}")
        raise Exception("Error")
    return response.json()

vector search 的部分參考前幾篇的 query 加上 ES 的 python client,回傳至多 20 筆資料,要注意的是,最後要傳給 LLM 的是原始的電影介紹文字內容,而不是 vector 。

def get_movie_from_es(index_name, question):
    vector_search ={
        "query": {
            "knn": {
            "field": "overview_vector",
            "query_vector": embedding(model_id, question),
            "k": 20,
            "num_candidates": 100
            }
        }
    }
    r = es_cli.search(index=index_name, body=vector_search)
    output_movie_list = []
    for hit in r['hits']['hits']:
        movie_title = hit['_source']['title']
        movie_overview = hit['_source']['overview']
        output_movie_list.append(f"{movie_title}: {movie_overview}")
    
    return "\n\n".join(output_movie_list)

接著結合前一篇的 prompt 就完成了,整個 script 如下:

from openai import OpenAI
import  elasticsearch
import requests
import argparse

def embedding(model_id, texts):
    # hf_token = os.getenv("HF_TOKEN")
    api_url = f"https://api-inference.huggingface.co/pipeline/feature-extraction/{model_id}"
    headers = {"Authorization": f"Bearer {hf_token}"}
    body = {"inputs": texts, "options":{"wait_for_model":True}}
    response = requests.post(api_url, headers=headers, json=body)
    if response.status_code != 200:
        print(f"Error: {response.status_code}, {response.text}")
        raise Exception("Error")
    return response.json()

def get_prompt(instruction, question, context):
    prompt = f"""
    Instructions:
    {instruction}

    Context:
    {context}

    Question: 
    {question}
    """
    return prompt

def get_movie_from_es(index_name, question):
    vector_search ={
        "query": {
            "knn": {
            "field": "overview_vector",
            "query_vector": embedding(model_id, question),
            "k": 20,
            "num_candidates": 100
            }
        }
    }
    r = es_cli.search(index=index_name, body=vector_search)
    output_movie_list = []
    for hit in r['hits']['hits']:
        movie_title = hit['_source']['title']
        movie_overview = hit['_source']['overview']
        output_movie_list.append(f"{movie_title}: {movie_overview}")
    
    return "\n\n".join(output_movie_list)

def get_rag(prompt):
    client = OpenAI(api_key=OPEN_AI_KEY)
    completion = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            {
                "role": "user",
                "content": prompt
            }
        ]
    )
    return completion.choices[0].message.content

if __name__ == "__main__":

    argparse = argparse.ArgumentParser()
    argparse.add_argument("--question", type=str, help="The question you want to ask")
    question = argparse.parse_args().question
    # question = "請推薦我黑道主題的電影"
    
    instruction = """
    你是我一個電影熱愛者,熟知各類型熱門電影資訊,經常有人來徵詢你不同的建議。
    但如果沒有推薦的電影,可以說沒有想法或是沒有推薦的,請只從提供的資訊中尋找推薦的電影。
    當推薦時你會提供電影名稱和關於這部電影的簡單描述。"""

    model_id = "intfloat/multilingual-e5-small"

    es_cli = elasticsearch.Elasticsearch("http://localhost:9200")
    index_name = 'tmdb_top_rated_movies_e5_small'
    context = get_movie_from_es(index_name, question)
    
    prompt = get_prompt(instruction, question, context)
    suggestion = get_rag(prompt)
    print(suggestion)

將 script 存成 movie_suggest.py ,就得到一個超級陽春電影推薦小幫手了。

python movie_suggest.py --question 請推薦我黑道主題的電影 得到的回答如下:

以下是幾部黑道主題的電影推薦:

1. **M就是兇手 (M)**:
   這部電影是影史上首部以變態殺手為題材的作品,講述了在德國柏林,一名連續殺手所引發的恐慌,警察和黑幫都參與了抓捕的鬥爭。這部影片探討了社會的黑暗面和暴力的影響,堪稱經典之作。

2. **神鬼無間 (The Departed)**:
   這部由馬丁·史柯西斯執導的影片,是對香港電影《無間道》的完美翻拍。故事圍繞波士頓的黑幫和警方的鬥爭,描繪了臥底警察和黑幫之間的緊張局勢,展現了身份和忠誠的複雜性。

3. **黑獄亡魂 (The Third Man)**:
   這部經典黑色電影以二次大戰後的維也納為背景,透過一名小說家的調查,引出了一系列與黑市有關的神秘事件。影片在展示陰暗角落的同時,展現了人性中的自私和善惡的對立。

這些作品都在不同的層面上探討了黑道文化與社會的關係,十分值得一看。

OpenAi 等 LLM 崛起、各大工具搶著結合並不是沒有其道理的,截至目前為止的操作都沒有任何艱深難懂的理論、算法、數學計算等,卻完成了在 AI 出現前可能需要大量工程的應用。

但 AI 相關的內容就到這,下一篇會看看 ES 跟 data pipeline(ETL / ELT) 有關的功能。


上一篇
2024 鐵人賽 Day26: How to RAG - prompt
下一篇
2024 鐵人賽 Day28: Ingest Pipeline
系列文
重新開始 elasticsearch 29
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言