Challenge 4: Update the retriever to fetch documents

Previous Challenge Next Challenge

Introduction

Now it is time to take the transformed query created in the previous steps and search for relevant movies (and their data) in the vector database.

We’re building a Retriever that’s integrated into a Flow. A working retriever takes a user query, transforms it into a vector embedding, and instructs our vector database to search for relevant documents. This process is entirely code-driven and doesn’t involve any prompts. We embed the Retriever within its own Flow (like we did with the prompts in earlier exercises) to create a modular and reusable component for our AI workflow. This allows us to organize the retrieval process, provide context to the retriever, and add flexibility in how we handle the retrieved documents. It also improves the testability of our application by allowing us to test the retrieval process independently. The retriver defined in our code is just a skeleton and doesn’t perform any embedding creation or searches on the Postgres db. You will be implementing the necessary functionality to do that in this challenge. The finished retriever flow should return a list of documents that are relevant to the user’s query.

The retriever also doesn’t interact with a LLM. Instead it will work with an embedding model to generate a vector representation of the query.

You need to perform the following steps:

  1. Write code that takes the query and transforms it into a vector embedding. This is because the vector db searches for vectors and not for text. So, you take your textual-query and transform it into a vector so that the db can return documents that have a similar representation to your search vector.
  2. Perform a search on the vector db based on the embedding and retrieve the following elements for each relevant movie (plot, title, actors, director, rating, runtime_mins, poster, released, content, genre).

You can do this with GoLang or TypeScript. Refer to the specific sections on how to continue.

Description

GoLang Retriever FLow

Pre-requisites

  • Make sure the Genkit UI is up and running at http://localhost:4002
  • Make sure that the movies documents are in the local database (if not, rerun challenge 1).

Challenge-steps

  1. Go to chat_server_go/cmd/standaloneFlows/docRetrieverFlow.go. You should see code that looks like this in the method DefineRetriever. This retriever just returns an empty document list.

     // define the retriever
     func DefineRetriever(maxRetLength int, db *sql.DB, embedder ai.Embedder) ai.Retriever {
      f := func(ctx context.Context, req *ai.RetrieverRequest) (*ai.RetrieverResponse, error) {
       // create a default empty response
       retrieverResponse := &ai.RetrieverResponse{
        Documents: make([]*ai.Document, 0, maxRetLength),
       }
             // returning the default response
             return retrieverResponse, nil
      }
      // return the retriever
      return ai.DefineRetriever("pgvector", "movieRetriever", f)
     }
    
  2. Go to the genkit ui and find Flows/movieDocFlow. Enter the following in the input and run the flow.

     {
         "query": "horror movie"
     }
    
  3. You should see an output that looks like this:

     {
         "documents": []
     }
    
  4. Edit the code to search for an retriver the relevant documents. See the instructions and hints in the code for guidance.

TypeScript Retriever Flow

Pre-requisites

  • Make sure the Genkit UI is up and running at http://localhost:4003
  • Make sure that the movies documents are in the local database (if not, rerun challenge 1).

Challenge-steps

  1. Go to js/flows-js/src/docRetriever.ts. You should see code that looks like this in the method defineRetriever. This retriever just returns an empty document list.

     // define the retriever
     const sqlRetriever = defineRetriever(
       {
         name: 'movies',
         configSchema: RetrieverOptionsSchema,
       },
       async (query, options) => {
         const db = await openDB();
         if (!db) {
           throw new Error('Database connection failed');
         }
         return {
         // returns empty document list
           documents: [] as Document[],
         };
       }
     );
    
  2. Go to the genkit ui and find Flows/movieDocFlow. Enter the following in the input and run the flow.

     {
         "query": "horror movie"
     }
    
  3. You should see an output that looks like this:

      []
    
  4. Edit the code to search for relevant documents and return these documents. See the instructions and hints in the code for guidance.

Success Criteria

Note: What to do if you’ve made the necessary change in the code files and still see weird output in the UI? Changing the code in the code files should automatically refresh it in the UI. Sometimes, however, genkit fails to autoupdate the prompt/flow in the UI after you’ve made the change in code. Hitting refresh on the browser (afer you’ve made and saved the code change) and reloading the UI page should fix it.

  1. The retriever should return relevant documents. The input of:

     {
         "query": "drama movies"
     }
    

    Should return a model output like that below. The response is truncated in the output below. But, you should see something that resembles following:

         [
              {
             "title": "Power of Love",
             "genres": "Drama, Romance",
             "rating": "4.7",
             "plot": "A cynical journalist, jaded by the world's cruelty, is assigned to cover a story about a small town where a mysterious force seems to be uniting its residents. As he investigates, he discovers the source of this power is an unlikely love story, one that challenges his own beliefs and forces him to confront the transformative potential of human connection.  He finds himself drawn into the story, questioning his own cynicism and ultimately finding redemption through the power of love.",
             "released": 2008,
             "director": "Neil Desai",
             "actors": "Mei Zhang,  Leymah Gbowee",
             "poster": "https://storage.googleapis.com/generated_posters/poster_408.png"
           },
              
           {
             "title": "A Noble Sacrifice",
             "genres": "Drama, Thriller",
             "rating": "3.2",
             "plot": "A renowned scientist, Dr. Emily Carter, discovers a cure for a deadly pandemic, but it comes at a devastating cost: she must sacrifice her own life to activate the cure.  Torn between her desire to save humanity and her fear of leaving her young daughter behind, Emily faces an impossible choice.  As the world watches, she makes a heart-wrenching decision, leaving behind a legacy of hope and a profound question about the true meaning of sacrifice.  The film explores the emotional journey of Emily and her daughter, as they grapple with the weight of her decision and the enduring power of love.",
             "released": 2006,
             "director": "David Hoffmann",
             "actors": "Emma Bernard,  Ng Wai Man",
             "poster": "https://storage.googleapis.com/generated_posters/poster_315.png"
           },
         ]
    

Learning Resources

Previous Challenge Next Challenge