🪟 Windows TippsThe Gemini desktop app is now available for Windows(11.09.2026 um 17:06 Uhr)
🔧 AI Nachrichten ChatGPT automatically logged out [Fix](12.09.2026 um 17:09 Uhr)
⚠️ Malware / Trojaner / VirenWindows 11 just dropped the tool ransomware abused, Microsoft says don’t restore WMIC(10.09.2026 um 20:11 Uhr)
🪟 Windows TippsServertimeout in Outlook über 10 Minuten verlängern(12.09.2026 um 15:10 Uhr)
🔧 AI Nachrichten Stealing AI Reasoning Traces(08.09.2026 um 12:20 Uhr)
🪟 Windows TippsThe Gemini desktop app is now available for Windows(11.09.2026 um 17:06 Uhr)
🔧 AI Nachrichten ChatGPT automatically logged out [Fix](12.09.2026 um 17:09 Uhr)
⚠️ Malware / Trojaner / VirenWindows 11 just dropped the tool ransomware abused, Microsoft says don’t restore WMIC(10.09.2026 um 20:11 Uhr)
🪟 Windows TippsServertimeout in Outlook über 10 Minuten verlängern(12.09.2026 um 15:10 Uhr)
🔧 AI Nachrichten Stealing AI Reasoning Traces(08.09.2026 um 12:20 Uhr)

🔧 Programmierung 🕛 vor 2 Jahren 16 Min Lesezeit
0

Build a RAG application to learn Angular using langchhtain.js, nestjs, Htmx, and Gemma 2

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

In this blog post, I describe how to use Langchain, NestJS, and Gemma 2 to build an RAG application about an Angular book in PDF format. Then, the HTMX and Handlebar template engine render the responses in a list. The application uses Langchain and its built-in PDF loader to load the PDF book and split the document into chunks. Then, Langchain uses the Gemini embedding text model to represent the documents into vectors and persist the vectors into a vector database. The vector store retriever provides the context for the large language model (LLM) to find information in its data to generate correct responses.






Set up environment variables






CODE
PORT=3001
GROQ_API_KEY=<GROQ API KEY>
GROQ_MODEL=gemma2-9b-it
GEMINI_API_KEY=<GEMINI API KEY>
GEMINI_TEXT_EMBEDDING_MODEL=text-embedding-004
HUGGINGFACE_API_KEY=<Huggingface API KEY>
HUGGINGFACE_EMBEDDING_MODEL=BAAI/bge-small-en-v1.5
QDRANT_URL=<Qdrant URL>
QDRANT_APK_KEY=<Qdrant API KEY>






Navigate to , sign up and register a new API Key. Replace the API Key to GROQ_API_KEY.



Navigate to Huggingface, , sign up and create a Qdrant space. Replace the URL to QDRANT_URL. Replace the API Key to QDRANT_API_KEY.






Install the dependencies






CODE
npm i -save-exact @google/generative-ai @huggingface/inference
@langchain/community @langchain/core @langchain/google-genai
@langchain/groq @langchain/qdrant @nestjs/config @nestjs/swagger
@nestjs/throttler class-transformer class-validator compression hbs
langchain pdf-parse









CODE
npm i -save-exact –save-dev @commitlint/cli 
@commitlint/config-conventional
husky lint-staged









Define the configuration in the application



Create a src/configs folder and add a configuration.ts to it




CODE
export default () => ({
port: parseInt(process.env.PORT, 10) || 3000,
groq: {
apiKey: process.env.GROQ_API_KEY || '',
model: process.env.GROQ_MODEL || 'gemma2-9b-it',
},
gemini: {
apiKey: process.env.GEMINI_API_KEY || '',
embeddingModel: process.env.GEMINI_TEXT_EMBEDDING_MODEL || 'text-embedding-004',
},
huggingface: {
apiKey: process.env.HUGGINGFACE_API_KEY || '',
embeddingModel: process.env.HUGGINGFACE_EMBEDDING_MODEL || 'BAAI/bge-small-en-v1.5',
},
qdrant: {
url: process.env.QDRANT_URL || 'http://localhost:6333',
apiKey: process.env.QDRANT_APK_KEY || '',
},
});









Create a Groq Module



Generate a Groq module, a controller and a service.




CODE
nest g mo groq
nest g s groq/application/groq --flat
nest g co groq/presenters/http/groq --flat









Add a chat model



Define a Groq configuration type, application/types/groq-config.type.ts, in the module. The configuration service converts the configuration values to a custom Object.




CODE
export type GroqConfig = {
model: string;
apiKey: string;
};






Add a custom provider to provide an instance of GroqChatModel. Create a groq.constant.ts file under application/constants folder.




CODE
// application/constants/groq.constant.ts

export const GROQ_CHAT_MODEL = 'GROQ_CHAT_MODEL';









CODE
// application/providers/groq-chat-model.provider.ts

import { ChatGroq } from '@langchain/groq';
import { Provider } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { GROQ_CHAT_MODEL } from '~groq/application/constants/groq.constant';
import { GroqConfig } from '~groq/application/types/groq-config.type';

export const GroqChatModelProvider: Provider<ChatGroq> = {
provide: GROQ_CHAT_MODEL,
useFactory: (configService: ConfigService) => {
const { apiKey, model } = configService.get<GroqConfig>('groq');
return new ChatGroq({
apiKey,
model,
temperature: 0.1,
maxTokens: 2048,
streaming: false,
});
},
inject: [ConfigService],
};









Test the Groq Chat Model in a controller






CODE
import { MessageContent } from '@langchain/core/messages';
import { ChatPromptTemplate } from '@langchain/core/prompts';
import { ChatGroq } from '@langchain/groq';
import { Inject, Injectable } from '@nestjs/common';
import { GROQ_CHAT_MODEL } from './constants/groq.constant';

@Injectable()
export class GroqService {
constructor(@Inject(GROQ_CHAT_MODEL) private model: ChatGroq) {}

async generateText(input: string): Promise<MessageContent> {
const prompt = ChatPromptTemplate.fromMessages([
['system', 'You are a helpful assistant'],
['human', '{input}'],
]);

const chain = prompt.pipe(this.model);
const response = await chain.invoke({
input,
});

return response.content;
}
}






The GroqService service has a method to take a query and ask the model to generate a text response




CODE
@Controller('groq')
export class GroqController {
constructor(private service: GroqService) {}

@Get()
testChain(): Promise<MessageContent> {
return this.service.generateText('What is Agentic RAG?');
}
}









Export the chat model from the module






CODE
import { Module } from '@nestjs/common';
import { GroqChatModelProvider } from './application/providers/groq-chat-model.provider';
import { GroqService } from './application/groq.service';
import { GroqController } from './presenters/http/groq.controller';

@Module({
providers: [GroqChatModelProvider, GroqService],
controllers: [GroqController],
exports: [GroqChatModelProvider],
})
export class GroqModule {}









Create a vector store module






CODE
nest g mo vectorStore
nest g s application/vectorStore --flat









Add configuration types



Define configuration types under application/types folder.



This is the configuration type of embedding model. This application supports both Gemini Text Embedding model and Huggingface Inference Embedding Model.




CODE
// application/types/embedding-model-config.type.ts

export type EmbeddingModelConfig = {
apiKey: string;
embeddingModel: string;
};






The application supports memory vector store and Qdrant vector store. Therefore, the application has Qdrant configuration.




CODE
// application/types/qdrant-database-config.type.ts

export type QdrantDatabaseConfig = {
apiKey: string;
url: string;
};






This configuration stores the split documents, vector database type and embedding model.




CODE
export type VectorDatabasesType = 'MEMORY' | 'QDRANT';









CODE
// application/types/vector-store-config.type.ts

import { Document } from '@langchain/core/documents';
import { Embeddings } from '@langchain/core/embeddings';
import { VectorDatabasesType } from './vector-databases.type';

export type VectorDatabaseFactoryConfig = {
docs: Document<Record<string, any>>[];
type: VectorDatabasesType;
embeddings: Embeddings;
};

export type DatabaseConfig = Omit<VectorDatabaseFactoryConfig, 'type'>;









Create a configurable embedding model






CODE
export type EmbeddingModels = 'GEMINI_AI' | 'HUGGINGFACE_INFERENCE';









CODE
import { TaskType } from '@google/generative-ai';
import { HuggingFaceInferenceEmbeddings } from '@langchain/community/embeddings/hf';
import { Embeddings } from '@langchain/core/embeddings';
import { GoogleGenerativeAIEmbeddings } from '@langchain/google-genai';
import { InternalServerErrorException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { EmbeddingModelConfig } from '../types/embedding-model-config.type';
import { EmbeddingModels } from '../types/embedding-models.type';

function createGeminiTextEmbeddingModel(configService: ConfigService) {
const { apiKey, embeddingModel: model } = configService.get<EmbeddingModelConfig>('gemini');
return new GoogleGenerativeAIEmbeddings({
apiKey,
model,
taskType: TaskType.RETRIEVAL_DOCUMENT,
title: 'Angular Book',
});
}

function createHuggingfaceInferenceEmbeddingModel(configService: ConfigService) {
const { apiKey, embeddingModel: model } = configService.get<EmbeddingModelConfig>('huggingface');
return new HuggingFaceInferenceEmbeddings({
apiKey,
model,
});
}

export function createTextEmbeddingModel(configService: ConfigService, embeddingModel: EmbeddingModels): Embeddings {
if (embeddingModel === 'GEMINI_AI') {
return createGeminiTextEmbeddingModel(configService);
} else if (embeddingModel === 'HUGGINGFACE_INFERENCE') {
return createHuggingfaceInferenceEmbeddingModel(configService);
} else {
throw new InternalServerErrorException('Invalid type of embedding model.');
}
}






The createGeminiTextEmbeddingModel function instantiates and returns a Gemini text embedding model. Similarly, the createHuggingfaceInferenceEmbeddingModel instantiates and returns a huggingface inference embedding model. Finally, the createTextEmbeddingModel function is a factory method that creates the embedding model based on the embedding model flag.






Create a configurable vector store retriever



Define a contract of a Vector Database Service




CODE
// application/interfaces/vector-database.interface.ts

import { VectorStore, VectorStoreRetriever } from '@langchain/core/vectorstores';
import { DatabaseConfig } from '../types/vector-store-config.type';

export interface VectorDatabase {
init(config: DatabaseConfig): Promise<void>;
asRetriever(): VectorStoreRetriever<VectorStore>;
}









CODE
import { VectorStore, VectorStoreRetriever } from '@langchain/core/vectorstores';
import { Injectable, Logger } from '@nestjs/common';
import { MemoryVectorStore } from 'langchain/vectorstores/memory';
import { VectorDatabase } from '../interfaces/vector-database.interface';
import { DatabaseConfig } from '../types/vector-store-config.type';

@Injectable()
export class MemoryVectorDBService implements VectorDatabase {
private readonly logger = new Logger(MemoryVectorDBService.name);
private vectorStore: VectorStore;

async init({ docs, embeddings }: DatabaseConfig): Promise<void> {
this.logger.log('MemoryVectorStoreService init called');
this.vectorStore = await MemoryVectorStore.fromDocuments(docs, embeddings);
}

asRetriever(): VectorStoreRetriever<VectorStore> {
return this.vectorStore.asRetriever();
}
}






The MemoryVectorDBService implements the interface, persists the vectors into the memory store, and returns the vector store retriever.




CODE
import { VectorStore, VectorStoreRetriever } from '@langchain/core/vectorstores';
import { QdrantVectorStore } from '@langchain/qdrant';
import { Injectable, InternalServerErrorException, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { QdrantClient } from '@qdrant/js-client-rest';
import { VectorDatabase } from '../interfaces/vector-database.interface';
import { QdrantDatabaseConfig } from '../types/qdrant-database-config.type';
import { DatabaseConfig } from '../types/vector-store-config.type';

const COLLECTION_NAME = 'angular_evolution_collection';

@Injectable()
export class QdrantVectorDBService implements VectorDatabase {
private readonly logger = new Logger(QdrantVectorDBService.name);
private vectorStore: VectorStore;

constructor(private configService: ConfigService) {}

async init({ docs, embeddings }: DatabaseConfig): Promise<void> {
this.logger.log('QdrantVectorStoreService init called');
const { url, apiKey } = this.configService.get<QdrantDatabaseConfig>('qdrant');
const client = new QdrantClient({ url, apiKey });
const { exists: isCollectionExists } = await client.collectionExists(COLLECTION_NAME);
if (isCollectionExists) {
const isDeleted = await client.deleteCollection(COLLECTION_NAME);
if (!isDeleted) {
throw new InternalServerErrorException(`Unable to delete ${COLLECTION_NAME}`);
}
this.logger.log(`QdrantVectorStoreService deletes ${COLLECTION_NAME}. Result -> ${isDeleted}`);
}

const size = (await embeddings.embedQuery('test')).length;
const isSuccess = await client.createCollection(COLLECTION_NAME, {
vectors: { size, distance: 'Cosine' },
});

if (!isSuccess) {
throw new InternalServerErrorException(`Unable to create collection ${COLLECTION_NAME}`);
}

this.vectorStore = await QdrantVectorStore.fromDocuments(docs, embeddings, {
client,
collectionName: COLLECTION_NAME,
});
}

asRetriever(): VectorStoreRetriever<VectorStore> {
return this.vectorStore.asRetriever();
}
}






The QdrantVectorDBService implements the interface, persists the vectors into the Qdrant vector database, and returns the vector store retriever.




CODE
// application/vector-databases/create-vector-database.t

import { InternalServerErrorException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { VectorDatabasesType } from '../types/vector-databases.type';
import { MemoryVectorDBService } from './memory-vector-db.service';
import { QdrantVectorDBService } from './qdrant-vector-db.service';

export function createVectorDatabase(type: VectorDatabasesType, configService: ConfigService) {
if (type === 'MEMORY') {
return new MemoryVectorDBService();
} else if (type === 'QDRANT') {
return new QdrantVectorDBService(configService);
}
throw new InternalServerErrorException(`Invalid vector store type: ${type}`);
}






The function instantiates the database service based on the database type.






Create document chunks from an Angular PDF book



Copy the book to the assets folder




CODE
import { PDFLoader } from '@langchain/community/document_loaders/fs/pdf';
import { RecursiveCharacterTextSplitter } from '@langchain/textsplitters';

const splitter = new RecursiveCharacterTextSplitter({
chunkSize: 1000,
chunkOverlap: 100,
});

export async function loadPdf(path: string) {
const loader = new PDFLoader(path);

const docs = await loader.load();
const splitDocs = await splitter.splitDocuments(docs);
return splitDocs;
}






The loadPdf function uses the pdf loader to load the PDF file, and split the document into many chunks.




CODE
import { Embeddings } from '@langchain/core/embeddings';
import { VectorStore, VectorStoreRetriever } from '@langchain/core/vectorstores';
import { Inject, Injectable, Logger } from '@nestjs/common';
import path from 'path';
import { appConfig } from '~configs/root-path.config';
import { ANGULAR_EVOLUTION_BOOK, TEXT_EMBEDDING_MODEL, VECTOR_DATABASE } from './constants/rag.constant';
import { VectorDatabase } from './interfaces/vector-database.interface';
import { loadPdf } from './loaders/pdf-loader';

@Injectable()
export class VectorStoreService {
private readonly logger = new Logger(VectorStoreService.name);

constructor(
@Inject(TEXT_EMBEDDING_MODEL) embeddings: Embeddings,
@Inject(VECTOR_DATABASE) private dbService: VectorDatabase,
) {
this.createDatabase(embeddings, this.dbService);
}

private async createDatabase(embeddings: Embeddings, dbService: VectorDatabase) {
const docs = await this.loadDocuments();
await dbService.init({ docs, embeddings });
}

private async loadDocuments() {
const bookFullPath = path.join(appConfig.rootPath, ANGULAR_EVOLUTION_BOOK);
const docs = await loadPdf(bookFullPath);
this.logger.log(`number of docs -> ${docs.length}`);
return docs;
}

asRetriever(): VectorStoreRetriever<VectorStore> {
this.logger.log(`return vector retriever`);
return this.dbService.asRetriever();
}
}






The VectorStoreService stores the PDF book into the vector database, and returns the vector store retriever.






Make the module a dynamic module






CODE
import { DynamicModule, Module } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { TEXT_EMBEDDING_MODEL, VECTOR_DATABASE, VECTOR_STORE_TYPE } from './application/constants/rag.constant';
import { createTextEmbeddingModel } from './application/embeddings/create-embedding-model';
import { EmbeddingModels } from './application/types/embedding-models.type';
import { VectorDatabasesType } from './application/types/vector-databases.type';
import { createVectorDatabase, MemoryVectorDBService, QdrantVectorDBService } from './application/vector-databases';
import { VectorStoreTestService } from './application/vector-store-test.service';
import { VectorStoreService } from './application/vector-store.service';
import { VectorStoreController } from './presenters/http/vector-store.controller';

@Module({
providers: [VectorStoreService, VectorStoreTestService, MemoryVectorDBService, QdrantVectorDBService],
controllers: [VectorStoreController],
exports: [VectorStoreService],
})
export class VectorStoreModule {
static register(embeddingModel: EmbeddingModels, vectorStoreType: VectorDatabasesType): DynamicModule {
return {
module: VectorStoreModule,
providers: [
{
provide: TEXT_EMBEDDING_MODEL,
useFactory: (configService: ConfigService) => createTextEmbeddingModel(configService, embeddingModel),
inject: [ConfigService],
},
{
provide: VECTOR_STORE_TYPE,
useValue: vectorStoreType,
},
{
provide: VECTOR_DATABASE,
useFactory: (type: VectorDatabasesType, configService: ConfigService) =>
createVectorDatabase(type, configService),
inject: [VECTOR_STORE_TYPE, ConfigService],
},
],
};
}
}






The VectorStoreModule is a dynamic module; the embedding model and vector database are configurable. The register static method create text embedding module and vector database based on the configuration.






Create an RAG module



The rag module is responsible for creating a langchain chain that asks the model to generate responses.




CODE
nest g mo ragTechBook
nest g s ragTechBook/application/rag --flat
nest g s ragTechBook/presenters/http/rag --flat









Create the RAG Service






CODE
// application/constants/prompts.constant.ts

import { ChatPromptTemplate, MessagesPlaceholder } from '@langchain/core/prompts';

const qaSystemPrompt = `You are an assistant for question-answering tasks.
Use the following pieces of retrieved context to answer the question.
If you don't know the answer, just say that you don't know.

{context}`
;

export const qaPrompt = ChatPromptTemplate.fromMessages([
['system', qaSystemPrompt],
new MessagesPlaceholder('chat_history'),
['human', '{question}'],
]);

const contextualizeQSystemPrompt = `Given a chat history and the latest user question
which might reference context in the chat history, formulate a standalone question
which can be understood without the chat history. Do NOT answer the question,
just reformulate it if needed and otherwise return it as is.`
;

export const contextualizeQPrompt = ChatPromptTemplate.fromMessages([
['system', contextualizeQSystemPrompt],
new MessagesPlaceholder('chat_history'),
['human', '{question}'],
]);






This constant file stores some prompts for the Langchain chains.




CODE
import { StringOutputParser } from '@langchain/core/output_parsers';
import { ChatGroq } from '@langchain/groq';
import { contextualizeQPrompt } from '../constants/prompts.constant';

export function createContextualizedQuestion(llm: ChatGroq) {
const contextualizeQChain = contextualizeQPrompt.pipe(llm).pipe(new StringOutputParser());

return (input: Record<string, unknown>) => {
if ('chat_history' in input) {
return contextualizeQChain;
}
return input.question;
};
}






This function creates a chain that formulates a question without relying on the chat history.




CODE
import { BaseMessage } from '@langchain/core/messages';
import { Runnable, RunnablePassthrough, RunnableSequence } from '@langchain/core/runnables';
import { ChatGroq } from '@langchain/groq';
import { Inject, Injectable } from '@nestjs/common';
import { formatDocumentsAsString } from 'langchain/util/document';
import { GROQ_CHAT_MODEL } from '~groq/application/constants/groq.constant';
import { VectorStoreService } from '~vector-store/application/vector-store.service';
import { createContextualizedQuestion } from './chain-with-history/create-contextual-chain';
import { qaPrompt } from './constants/prompts.constant';
import { ConversationContent } from './types/conversation-content.type';

@Injectable()
export class RagService {
private chat_history: BaseMessage[] = [];

constructor(
@Inject(GROQ_CHAT_MODEL) private model: ChatGroq,
private vectorStoreService: VectorStoreService,
) {}

async ask(question: string): Promise<ConversationContent[]> {
const contextualizedQuestion = createContextualizedQuestion(this.model);
const retriever = this.vectorStoreService.asRetriever();

try {
const ragChain = RunnableSequence.from([
RunnablePassthrough.assign({
context: (input: Record<string, unknown>) => {
if ('chat_history' in input) {
const chain = contextualizedQuestion(input);
return (chain as Runnable).pipe(retriever).pipe(formatDocumentsAsString);
}
return '';
},
}),
qaPrompt,
this.model,
]);

const aiMessage = await ragChain.invoke({ question, chat_history: this.chat_history });
this.chat_history = this.chat_history.concat(aiMessage);
if (this.chat_history.length > 10) {
this.chat_history.shift();
}

return [
{
role: 'Human',
content: question,
},
{
role: 'Assistant',
content: (aiMessage.content as string) || '',
},
];
} catch (ex) {
console.error(ex);
throw ex;
}
}
}






The RagService service is straightforward. The ask method submits the input to the chain and outputs a response. This method extracts the content from the response, stores the Human and AI messages in chat history in memory and returns the conversation to the template engine for rendering.






Add RAG Controller






CODE
import { IsNotEmpty, IsString } from 'class-validator';

export class AskDto {
@IsString()
@IsNotEmpty()
query: string;
}









CODE
@Controller('rag')
export class RagController {
constructor(private service: RagService) {}

@Post()
async ask(@Body() dto: AskDto): Promise<string> {
const conversation = await this.service.ask(dto.query);
return toDivRow(conversation);
}
}






The RAG controller submits the query to the chain, gets the results, and sends the HTML codes back to the template engine to render.






Import modules into RAG module






CODE
import { Module } from '@nestjs/common';
import { GroqModule } from '~groq/groq.module';
import { VectorStoreModule } from '~vector-store/vector-store.module';
import { RagService } from './application/rag.service';
import { RagController } from './presenters/http/rag.controller';

@Module({
imports: [GroqModule, VectorStoreModule.register('GEMINI_AI', 'MEMORY')],
providers: [RagService],
controllers: [RagController],
})
export class RagTechBookModule {}









Import RagModule to AppModule






CODE
import { RagTechBookModule } from '~rag-tech-book/rag-tech-book.module';

@Module({
imports: [
other imports
RagTechBookModule,
],
controllers: [AppController],
})
export class AppModule {}









Modify App Controller to render handlebar template






CODE
import { Controller, Get, Render } from '@nestjs/common';

@Controller()
export class AppController {
@Get()
@Render('index')
getHello(): Record<string, string> {
return {
title: 'Angular Tech Book RAG',
};
}
}






The App controller informs the Handlebar template engine to render index.hbs file.






HTMX and Handlebar Template Engine



This is a simple user interface to display the conversation




CODE
default.hbs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="description" content="Angular tech book RAG powed by gemma 2 LLM." />
<meta name="author" content="Connie Leung" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{{ title }}}</title>
<style>
*, *::before, *::after {
padding: 0;
margin: 0;
box-sizing: border-box;
}
</style>
<script src="https://cdn.tailwindcss.com?plugins=forms,typography"></script>
</head>
<body class="p-4 w-screen h-screen min-h-full">
<script src="https://unpkg.com/[email protected]" integrity="sha384-QWGpdj554B4ETpJJC9z+ZHJcA/i59TyjxEPXiiUgN2WmTyV5OEZWCD6gQhgkdpB/" crossorigin="anonymous"></script>
<div class="h-full grid grid-rows-[auto_1fr_40px] grid-cols-[1fr]">
{{> header }}
{{{ body }}}
{{> footer }}
</div>
</body>
</html>






The above is a default layout with a header, footer, and body. The body eventually displays the conversation between the AI and human. The head section imports tailwind to style the HTML elements and htmx to interact with the server.




CODE
<div>
<div class="mb-2 p-1 border border-solid border-[#464646] rounded-lg">
<p class="text-[1.25rem] mb-2 text-[#464646] underline">Architecture</p>
<ul>
<li class="text-[1rem]">Chat Model: Groq</li>
<li class="text-[1rem]">LLM: Gemma 2</li>
<li class="text-[1rem]">Embeddings: Gemini AI Embedding / HuggingFace Embedding</li>
<li class="text-[1rem]">Vector Store: Memory Vector Store / Qdrant Vector Store</li>
<li class="text-[1rem]">Retriever: Vector Store Retriever</li>
</ul>
</div>
<div id="chat-list" class="mb-4 h-[300px] overflow-y-auto overflow-x-auto">
<div class="flex text-[#464646] text-[1.25rem] italic underline">
<span class="w-1/5 p-1 border border-solid border-[#464646]">Role</span>
<span class="w-4/5 p-1 border border-solid border-[#464646]">Result</span>
</div>
</div>
<form id="rag-form" hx-post="/rag" hx-target="#chat-list" hx-swap="beforeend swap:1s">
<div>
<label>
<span class="text-[1rem] mr-1 w-1/5 mb-2 text-[#464646]">Question: </span>
<input type="text" name="query" class="mb-4 w-4/5 rounded-md p-2"
placeholder="Ask me something"
aria-placeholder="Placeholder to ask question to RAG"></input>
</label>
</div>
<button type="submit" class="bg-blue-500 hover:bg-blue-700 text-white p-2 text-[1rem] flex justify-center items-center rounded-lg">
<span class="mr-1">Send</span><img class="w-4 h-4 htmx-indicator" src="/images/spinner.gif">
</button>
</form>
</div>






A user can input the question in the text field and click the Send button. The button makes a POST request to /rag and appends the conversation to the list.



This is the end of my first langchain RAG application using the Gemma 2 model to generate the responses.






Resources



Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
The Gemini desktop app is now available for Windows
1 Quelle
ChatGPT automatically logged out [Fix]
1 Quelle
Windows 11 just dropped the tool ransomware abused, Microsoft says don’t restore WMIC
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Build a RAG application to learn Angular using langchhtain.js, nestjs, Htmx, and Gemma 2

Thematisch verwandte Begriffe: Build, application, learn, Angular · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...