strArr = new ArrayList<>();
+
+ String query = "select t.column_value as data from dbms_vector_chain.utl_to_chunks(?, json(?)) t";
+ try (PreparedStatement stmt = conn.prepareStatement(query)) {
+ stmt.setObject(1, content);
+ stmt.setObject(2, pref);
+ try (ResultSet rs = stmt.executeQuery()) {
+ while (rs.next()) {
+ String text = rs.getString("data");
+
+ ObjectMapper mapper = new ObjectMapper();
+ Chunk chunk = mapper.readValue(text, Chunk.class);
+ strArr.add(chunk.chunk_data);
+ }
+ }
+ }
+
+ return strArr.toArray(new String[strArr.size()]);
+ }
+
+ /**
+ * Creates a new {@link TextSegment} from the provided text and document.
+ *
+ *
+ * The segment inherits all metadata from the document. The segment also
+ * includes an "index" metadata key representing the segment position within
+ * the document.
+ *
+ * @param text The text of the segment.
+ * @param document The document to which the segment belongs.
+ * @param index The index of the segment within the document.
+ */
+ static TextSegment createSegment(String text, Document document, int index) {
+ Metadata metadata = document.metadata().copy().put(INDEX, String.valueOf(index));
+ return TextSegment.from(text, metadata);
+ }
+}
diff --git a/langchain4j-oracle/src/main/java/dev/langchain4j/model/oracle/Embedding.java b/langchain4j-oracle/src/main/java/dev/langchain4j/model/oracle/Embedding.java
new file mode 100644
index 00000000000..96eba8ebb01
--- /dev/null
+++ b/langchain4j-oracle/src/main/java/dev/langchain4j/model/oracle/Embedding.java
@@ -0,0 +1,11 @@
+package dev.langchain4j.model.oracle;
+
+public class Embedding {
+
+ public int embed_id;
+ public String embed_data;
+ public String embed_vector;
+
+ public Embedding() {
+ }
+}
diff --git a/langchain4j-oracle/src/main/java/dev/langchain4j/model/oracle/OracleEmbeddingModel.java b/langchain4j-oracle/src/main/java/dev/langchain4j/model/oracle/OracleEmbeddingModel.java
new file mode 100644
index 00000000000..74fabed68fb
--- /dev/null
+++ b/langchain4j-oracle/src/main/java/dev/langchain4j/model/oracle/OracleEmbeddingModel.java
@@ -0,0 +1,172 @@
+package dev.langchain4j.model.oracle;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import dev.langchain4j.data.document.splitter.oracle.Chunk;
+import dev.langchain4j.data.embedding.Embedding;
+import dev.langchain4j.data.segment.TextSegment;
+import dev.langchain4j.model.embedding.DimensionAwareEmbeddingModel;
+import dev.langchain4j.model.output.Response;
+
+import java.sql.Array;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import static java.util.stream.Collectors.toList;
+
+import oracle.jdbc.OracleConnection;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OracleEmbeddingModel extends DimensionAwareEmbeddingModel {
+
+ private static final Logger log = LoggerFactory.getLogger(OracleEmbeddingModel.class);
+
+ private final Connection conn;
+ private final String pref;
+ private final String proxy;
+ private boolean batching = true;
+
+ public OracleEmbeddingModel(Connection conn, String pref) {
+ this.conn = conn;
+ this.pref = pref;
+ this.proxy = "";
+ }
+
+ public OracleEmbeddingModel(Connection conn, String pref, String proxy) {
+ this.conn = conn;
+ this.pref = pref;
+ this.proxy = proxy;
+ }
+
+ void setBatching(boolean batching) {
+ this.batching = batching;
+ }
+
+ boolean getBatching() {
+ return this.batching;
+ }
+
+ static boolean loadOnnxModel(Connection conn, String dir, String onnxFile, String modelName) throws SQLException {
+ boolean result = false;
+
+ String query = "begin\n"
+ + " dbms_data_mining.drop_model(?, force => true);\n"
+ + " dbms_vector.load_onnx_model(?, ?, ?,\n"
+ + " json('{\"function\" : \"embedding\", \"embeddingOutput\" : \"embedding\" , \"input\": {\"input\": [\"DATA\"]}}'));\n"
+ + "end;";
+ PreparedStatement stmt = conn.prepareStatement(query);
+ stmt.setObject(1, modelName);
+ stmt.setObject(2, dir);
+ stmt.setObject(3, onnxFile);
+ stmt.setObject(4, modelName);
+ stmt.execute();
+ result = true;
+
+ return result;
+ }
+
+ @Override
+ public Response> embedAll(List textSegments) {
+ List texts = textSegments.stream()
+ .map(TextSegment::text)
+ .collect(toList());
+
+ return embedTexts(texts);
+ }
+
+ private Response> embedTexts(List inputs) {
+ List embeddings = new ArrayList<>();
+
+ try {
+ if (proxy != null && !proxy.isEmpty()) {
+ String query = "begin utl_http.set_proxy(?); end;";
+ try (PreparedStatement stmt = conn.prepareStatement(query)) {
+ stmt.setObject(1, proxy);
+ stmt.execute();
+ }
+ }
+
+ if (!batching) {
+ for (String input : inputs) {
+ String query = "select t.column_value as data from dbms_vector_chain.utl_to_embeddings(?, json(?)) t";
+ try (PreparedStatement stmt = conn.prepareStatement(query)) {
+ stmt.setObject(1, input);
+ stmt.setObject(2, pref);
+ try (ResultSet rs = stmt.executeQuery()) {
+ while (rs.next()) {
+ String text = rs.getString("data");
+
+ ObjectMapper mapper = new ObjectMapper();
+ dev.langchain4j.model.oracle.Embedding dbmsEmbedding = mapper.readValue(text, dev.langchain4j.model.oracle.Embedding.class);
+ Embedding embedding = new Embedding(toFloatArray(dbmsEmbedding.embed_vector));
+ embeddings.add(embedding);
+ }
+ }
+ }
+ }
+ } else {
+ // createOracleArray needs to passed a Clob array since vector_array_t is a table of clob
+ // if a String array is passed, will get ORA-17059: Failed to convert to internal representation
+ List