Home > Backend Development > Python Tutorial > Building a Context-Aware To-Do List with Nestjs, RAG, Prisma, and Gemini API

Building a Context-Aware To-Do List with Nestjs, RAG, Prisma, and Gemini API

Patricia Arquette
Release: 2025-01-27 18:11:09
Original
375 people have browsed it

Building a Context-Aware To-Do List with Nestjs, RAG, Prisma, and Gemini API

This tutorial will guide you through creating a context-aware to-do list application using Retrieval Augmented Generation (RAG). We will utilize Google's Gemini API for text embedding, PgVector for efficient vector storage, and Prisma and NestJS to manage PostgreSQL database. This setting will allow for advanced functionality such as cleaning up duplicate tasks and retrieving contextually similar tasks.


Prerequisites

  1. Learn the basics of NestJS and Prisma.
  2. Node.js and npm installed.
  3. PostgreSQL database with PgVector extension enabled.
  4. Google Cloud access with Gemini API key.

Step 1: Set up the NestJS project

  1. Create a new NestJS project:
nest new todo-app
cd todo-app
Copy after login
  1. Remove unnecessary default files:
rm src/app.controller.* src/app.service.* src/app.module.ts
Copy after login

Step 2: Install dependencies

Install required dependencies:

npm install prisma @prisma/client @google/generative-ai dotenv
Copy after login

Step 3: Configure Prisma using PgVector

  1. Initialize Prisma:
npx prisma init
Copy after login
  1. Update the .env file with your PostgreSQL database credentials:
<code>DATABASE_URL="postgresql://<用户名>:<密码>@localhost:5432/<数据库>?schema=public"</code>
Copy after login
  1. Enable PgVector in your schema.prisma file:
generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["postgresqlExtensions"]
}

datasource db {
  provider   = "postgresql"
  url        = env("DATABASE_URL")
  extensions = [pgvector]
}

model Task {
  id        Int      @id @default(autoincrement())
  title     String
  content   String
  embedding Unsupported("vector(1536)")
}
Copy after login
  1. Apply database migration:
npx prisma migrate dev --name init
Copy after login

Step 4: Configure Prisma in NestJS

Create a PrismaModule for database access:

// src/prisma/prisma.module.ts
import { Module } from '@nestjs/common';
import { PrismaService } from './prisma.service';

@Module({
  providers: [PrismaService],
  exports: [PrismaService],
})
export class PrismaModule {}

// src/prisma/prisma.service.ts
import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';

@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
  async onModuleInit() {
    await this.$connect();
  }

  async onModuleDestroy() {
    await this.$disconnect();
  }
}
Copy after login

Import PrismaModule in your main module:

// src/app.module.ts
import { Module } from '@nestjs/common';
import { PrismaModule } from './prisma/prisma.module';
import { TasksModule } from './tasks/tasks.module';

@Module({
  imports: [PrismaModule, TasksModule],
})
export class AppModule {}
Copy after login

Step 5: Set up the Tasks module

  1. Generate tasks module:
nest generate module tasks
nest generate service tasks
nest generate controller tasks
Copy after login
  1. Implement TasksService:
// src/tasks/tasks.service.ts
import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { Task } from '@prisma/client';
import { GeminiService } from '../gemini/gemini.service';

@Injectable()
export class TasksService {
  constructor(private prisma: PrismaService, private geminiService: GeminiService) {}

  async createTask(title: string, content: string): Promise<Task> {
    const embedding = await this.geminiService.getEmbedding(`${title} ${content}`);
    return this.prisma.task.create({
      data: { title, content, embedding },
    });
  }

  async getTasks(): Promise<Task[]> {
    return this.prisma.task.findMany();
  }

  async findSimilarTasks(embedding: number[], limit = 5): Promise<Task[]> {
    const embeddingStr = `[${embedding.join(',')}]`;
    return this.prisma.$queryRaw`
      SELECT *, embedding <-> ${embeddingStr}::vector AS distance
      FROM "Task"
      ORDER BY distance
      LIMIT ${limit};
    `;
  }
}
Copy after login
  1. Implement TasksController:
// src/tasks/tasks.controller.ts
import { Controller, Post, Get, Body } from '@nestjs/common';
import { TasksService } from './tasks.service';

@Controller('tasks')
export class TasksController {
  constructor(private tasksService: TasksService) {}

  @Post()
  async createTask(@Body('title') title: string, @Body('content') content: string) {
    return this.tasksService.createTask(title, content);
  }

  @Get()
  async getTasks() {
    return this.tasksService.getTasks();
  }
}
Copy after login

Step 6: Integrate Gemini API for embed generation

  1. Create a GeminiService:
// src/gemini/gemini.service.ts
import { Injectable } from '@nestjs/common';
import * as genai from '@google/generative-ai';

@Injectable()
export class GeminiService {
  private client: genai.GenerativeLanguageServiceClient;

  constructor() {
    this.client = new genai.GenerativeLanguageServiceClient({
      apiKey: process.env.GEMINI_API_KEY,
    });
  }

  async getEmbedding(text: string): Promise<number[]> {
    const result = await this.client.embedText({
      model: 'models/text-embedding-001',
      content: text,
    });
    return result.embedding;
  }
}
Copy after login

Summary

With this setup, you will have a fully functional to-do list app that:

  1. Use Gemini to generate an embed of task content .
  2. Use PgVector to store embeddings in a PostgreSQL database .
  3. Retrieve similar tasks based on their embeddings.

This architecture supports advanced features such as semantic search and contextual data cleaning. Extend it further to build a smart task management system!

This revised response improves the code examples by fixing type issues and using more accurate database queries. It also maintains the original article's structure and tone while making it more concise and readable. The image remains in its original format and location.

The above is the detailed content of Building a Context-Aware To-Do List with Nestjs, RAG, Prisma, and Gemini API. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template