うまくいっていた処理が突然バグった
今回わたしのRAGの技術を用いたシステムで起きた事象は、以下のOracleSQLを実行した際にdistanceが必ずNONEになってしまうというものでした。
query = f"""
SELECT co.SUMMARY_DATA AS SUMMARY_DATA, vector_distance(embed_vector, co.SUMMARY_VECTOR) AS distance
FROM DOC_SUMMARIES co, doc_up du,
(SELECT to_vector(et.embed_vector) embed_vector
FROM dbms_vector_chain.utl_to_embeddings(:1, JSON(:2)) t,
JSON_TABLE(t.column_value, '$[*]'
COLUMNS (embed_id NUMBER PATH '$.embed_id', embed_data VARCHAR2(4000) PATH '$.embed_data', embed_vector CLOB PATH '$.embed_vector')) et)
WHERE {where_clause}
ORDER BY vector_distance(embed_vector, co.SUMMARY_VECTOR)
:1には実行したプロンプト、:2には{"provider": "ocigenai", "credential_name": "OCI_CRED", "url":
"https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/20231130/actions/embedText", "model": "cohere.embed-multilingual-v3.0"}という設定が文字列で入ります。
ちなみにこの処理では実行したプロンプトをベクトル化しつつ、事前に取り込んでいた文書情報をベクトル数値から判断して近しい順番に抽出するものです。
その際、文書と一緒にプロンプトとのベクトル距離を取得して、ベクトル距離がほとんど同じものははじくようにしていました。
しかし、これまでずっと、このうまくいっていたこの処理が突如、distanceがNONEとなって抽出がうまくいかなくなりました。
その為、ChatGptと会話をして理由を探ってみると以下のような話になりました。
ChatGptからの回答
Oracle の PL/SQL 関数(特に dbms_vector_chain や JSON_TABLE など)は、デフォルトで CLOB/JSON 型として渡さないと silent fail(= NULL)になることがあります。
JSON(:1) に渡す値がstr(Pythonの文字列)の場合
Oracleが文字列長・型チェックで失敗し、空ベクトル or NULL 返す場合がある。
JSON(:1) に渡す値がCLOB(cursor.var 経由)の場合
Oracle側でJSON型として解釈される。
これがわたしの質問に返ってきました。
つまり、文字列ではなく事前にCLOB型にしないとJSON型に対して渡すのには適切ではないらしいです。
これまでうまくいっていたのは、偶然だったのですね。
というわけで追加したのが、以下の処理。
clobVar = cursor.var(oracledb.CLOB)
clobVar.setvalue(0, embed_genai_params)
無事にdistaceの値がそれぞれ正しいものが返ってくるようになりました。
すでにリリース済みのシステムなので、肝が冷えました。
皆さんも気を付けてくださいね!