[extensions/openai] Support undocumented base64 'encoding_format' param for compatibility with official OpenAI client
diff --git a/extensions/openai/script.py b/extensions/openai/script.py
index c168ec95b0..9eb35a4648 100644
--- a/extensions/openai/script.py
+++ b/extensions/openai/script.py
@@ -1,4 +1,6 @@
+import base64
 import json
+import numpy as np
 import os
 import time
 from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
@@ -45,6 +47,20 @@ def clamp(value, minvalue, maxvalue):
     return max(minvalue, min(value, maxvalue))
 
 
+def float_list_to_base64(float_list):
+    # Convert the list to a float32 array that the OpenAPI client expects
+    float_array = np.array(float_list, dtype="float32")
+
+    # Get raw bytes
+    bytes_array = float_array.tobytes()
+
+    # Encode bytes into base64
+    encoded_bytes = base64.b64encode(bytes_array)
+
+    # Turn raw base64 encoded bytes into ASCII
+    ascii_string = encoded_bytes.decode('ascii')
+    return ascii_string
+
 class Handler(BaseHTTPRequestHandler):
     def do_GET(self):
         if self.path.startswith('/v1/models'):
@@ -435,7 +451,13 @@ def do_POST(self):
 
             embeddings = embedding_model.encode(input).tolist()
 
-            data = [{"object": "embedding", "embedding": emb, "index": n} for n, emb in enumerate(embeddings)]
+            def enc_emb(emb):
+                # If base64 is specified, encode. Otherwise, do nothing.
+                if body.get("encoding_format", "") == "base64":
+                    return float_list_to_base64(emb)
+                else:
+                    return emb
+            data = [{"object": "embedding", "embedding": enc_emb(emb), "index": n} for n, emb in enumerate(embeddings)]
 
             response = json.dumps({
                 "object": "list",

The official Python OpenAI API client uses an undocumented `encoding_format` parameter on the `/v1/embeddings` endpoint by default.

https://github.com/openai/openai-python/blob/d6fa3bfaae69d639b0dd2e9251b375d7070bbef1/openai/api_resources/embedding.py#L25-L29

This PR adds support for the `encoding_format` parameter to maintain support as a drop-in replacement for the OpenAI API. Without this parameter, [llama_index](https://github.com/jerryjliu/llama_index), and possibly other langchain apps, may fail to work.