Skip to content

[Firestore] FieldValue.vector works well on top, but does not work in nested fields #2621

@mrkaraaslan

Description

@mrkaraaslan

Environment

  • Operating System version: firebase cloud functions
  • Firebase SDK version:
  • "firebase-admin": "^12.2.0",
  • "firebase-functions": "^5.0.1",
  • Firebase Product: Firestore
  • Node.js version: v18.20.3
  • NPM version: 10.7.0

Problem

FieldValue.vector works well on top, but does not work in nested fields

Steps to reproduce:

This code works well

const admin = require("firebase-admin");
const functions = require("firebase-functions");
const embedder = require("./create_embedding");

exports.autoCreateEmbedding = functions.runWith({memory: "1GB"})
    .firestore.document("z_embedding/{docId}").onCreate(async (snap) => {
      const fv = admin.firestore.FieldValue;
      const data = snap.data();
      const n = data.name;
      const n2 = data.name2;

      const tensorEmbedding1 = await embedder.createEmbeddingTensor(n);
      const tensorEmbedding2 = await embedder.createEmbeddingTensor(n2);
      const googleEmbedding1 = await embedder.createEmbeddingGoogle(n);
      const googleEmbedding2 = await embedder.createEmbeddingGoogle(n2);

      console.log(`created embeddings`);
      const te = {t1: fv.vector( tensorEmbedding1), t2: fv.vector(tensorEmbedding2)};
      const ge = {g1: fv.vector(googleEmbedding1), g2: fv.vector(googleEmbedding2)};
      // concat embeddings into one object
      const embeddings = {...te, ...ge}; // PROBLEM WILL BE HERE

      console.log(`updating embeddings`);
      try {
        await snap.ref.update(embeddings);
      } catch (error) {
        console.log("Error updating document: ", error);
      }
    });

What happened? How can we make the problem occur?
When I change the problem line from

const embeddings = {...te, ...ge}; // PROBLEM WILL BE HERE

to

const embeddings = {te, ge};
await snap.ref.update(embeddings);

operation fails with

Error updating document:  Error: 13 INTERNAL: An internal error occurred.

Relevant Code:

  createEmbeddingGoogle: async function(text) {
    const projectId = JSON.parse(process.env.FIREBASE_CONFIG).projectId;

    // SETUP MODEL
    const model = "text-multilingual-embedding-002";
    const clientOptions = {apiEndpoint: "us-central1-aiplatform.googleapis.com"};
    const endpoint = `projects/${projectId}/locations/us-central1/publishers/google/models/${model}`;
    const instances = [helpers.toValue({content: toSuperLower(text), taskType: "QUESTION_ANSWERING"})];
    const request = {endpoint, instances};
    const client = new PredictionServiceClient(clientOptions);

    // GET EMBEDDING
    const [response] = await client.predict(request);
    const prediction = response.predictions[0];
    const embeddings = prediction.structValue.fields.embeddings;
    const values = embeddings.structValue.fields.values.listValue.values;
    const embeddingsArray = values.map((value) => value.numberValue);
    return embeddingsArray;
  },

  createEmbeddingTensor: async function(text) {
    tf.setBackend("tensorflow");
    const model = await use.load();
    const embeddings = await model.embed(text);
    const embeddingsArray = embeddings.arraySync().flat();
    return embeddingsArray;
  },

Additional

To verify that I am creating the correct object format I tested with this and it works well

exports.autoCreateEmbedding = functions.runWith({memory: "1GB"})
    .firestore.document("z_embedding/{docId}").onCreate(async (snap) => {
      // const fv = admin.firestore.FieldValue;
      const data = snap.data();
      const n = data.name;
      const n2 = data.name2;

      // const tensorEmbedding1 = await embedder.createEmbeddingTensor(n);
      // const tensorEmbedding2 = await embedder.createEmbeddingTensor(n2);
      // const googleEmbedding1 = await embedder.createEmbeddingGoogle(n);
      // const googleEmbedding2 = await embedder.createEmbeddingGoogle(n2);

      console.log(`created embeddings`);
      const te = {t1: n, t2: n2};
      const ge = {g1: n, g2: n2};
      // concat embeddings into one object
      const embeddings = {te, ge};

      console.log(`updating embeddings`);
      try {
        await snap.ref.update(embeddings);
      } catch (error) {
        console.log("Error updating document: ", error);
      }
    });

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions