实例详解 | 借助 Langchain 和 Gemma 2 构建 RAG 应用

本文原作者:Connie Leung,谷歌开发者专家 (GDE),原文发布于:DEV Community

https://dev.to/railsstudent/build-a-rag-application-to-learn-angular-using-langchhtainjs-nestjs-htmx-and-gemma-2-5ggk

本文将为您介绍如何使用 LangChain、NestJS 和 Gemma 2 构建关于 PDF 格式 Angular 书籍的 RAG 应用。接着,HTMX 和 Handlebar 模板引擎将响应呈现为列表。应用使用 LangChain 及其内置的 PDF 加载器来加载 PDF 书籍,并将文档拆分为小块。然后,LangChain 使用 Gemini 嵌入文本模型将文档表示为向量,并将向量持久化存储到向量数据库中。向量存储检索器为大语言模型 (LLM) 提供上下文,以便在其数据中查找信息,从而生成正确的响应。

设置环境变量

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>

访问 https://aistudio.google.com/app/apikey,登录帐号,创建新的 API 密钥。将 API 密钥替换为 GEMINI_API_KEY。

访问 Groq Cloud: https://console.groq.com/,注册帐号并新建一个 API 密钥。将 API 密钥替换为 GROQ_API_KEY。

访问 Huggingface: https://huggingface.co/join,注册帐号,创建新的访问令牌。将访问令牌替换为 HUGGINGFACE_API_KEY。

访问 Qdrant: https://cloud.qdrant.io/,注册帐号,创建 Qdrant 空间。将网址替换为 QDRANT_URL。将 API 密钥替换为 QDRANT_API_KEY。

安装依赖项

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
npm i -save-exact –save-dev @commitlint/cli` `@commitlint/config-conventional` `husky lint-staged

定义应用的配置

创建 src/configs 文件夹并在其中添加 configuration.ts 文件。

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 || '',` `},``});

创建 Groq 模块

生成 Groq 模块、控制器和服务。

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

添加一个聊天模型

在模块中定义 Groq 配置类型,文件路径为 application/types/groq-config.type.ts。配置服务将配置值转换为自定义对象。

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

添加自定义提供程序以提供 GroqChatModel 的实例。在 application/constants 文件夹下创建 groq.constant.ts 文件。

// application/constants/groq.constant.ts``   ``export const GROQ_CHAT_MODEL = 'GROQ_CHAT_MODEL';
// 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],``};

在控制器中测试 Groq 聊天模型

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;` `}``}

GroqService 服务有一个方法,用于执行查询并要求模型生成文本响应。

@Controller('groq')``export class GroqController {` `constructor(private service: GroqService) {}``   ` `@Get()` `testChain(): Promise<MessageContent> {`   `return this.service.generateText('What is Agentic RAG?');` `}``}

从模块导出聊天模型

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 {}

创建向量存储模块

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

添加配置类型

在 application/types 文件夹下定义配置类型。

这是嵌入模型的配置类型。此应用同时支持 Gemini 文本嵌入模型和 Huggingface 推理嵌入模型。

// application/types/embedding-model-config.type.ts``   ``export type EmbeddingModelConfig = {` `apiKey: string;` `embeddingModel: string;``};

应用支持内存向量存储和 Qdrant 向量存储。因此,应用具有 Qdrant 配置。

// application/types/qdrant-database-config.type.ts``   ``export type QdrantDatabaseConfig = {` `apiKey: string;` `url: string;``};

此配置中存储了拆分后的文档、向量数据库类型和嵌入模型。

export type VectorDatabasesType = 'MEMORY' | 'QDRANT';
// 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'>;

创建可配置的嵌入模型

export type EmbeddingModels = 'GEMINI_AI' | 'HUGGINGFACE_INFERENCE';
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.');` `}``}

createGeminiTextEmbeddingModel 函数将实例化并返回 Gemini 文本嵌入模型。类似地,createHuggingfaceInferenceEmbeddingModel 将实例化并返回 Huggingface 推理嵌入模型。最后,createTextEmbeddingModel 函数是一个工厂方法,根据嵌入模型标志创建嵌入模型。

创建可配置的向量存储检索器

定义向量数据库服务接口

// 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>;``}
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();` `}``}

MemoryVectorDBService 实现了接口,将向量持久化存储到内存存储中,并返回向量存储检索器。

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();` `}``}

QdrantVectorDBService 实现了接口,将向量持久化存储到 Qdrant 向量数据库中,并返回向量存储检索器。

// 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}`);```}

函数将根据数据库类型实例化数据库服务。

从 Angular PDF 书籍创建文档块

将书籍复制到 assets 文件夹

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;``}

loadPdf 函数使用 PDF 加载器来加载 PDF 文件,并将文档拆分为多个小块。

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();` `}``}

VectorStoreService 将 PDF 书籍存储到向量数据库中,并返回向量存储检索器。

将模块设为动态模块

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],`       `},`     `],`   `};` `}``}

VectorStoreModule 是一个动态模块。嵌入模型和向量数据库均可自行配置。注册静态方法根据配置创建文本嵌入模块和向量数据库。

创建 RAG 模块

RAG 模块负责创建 LangChain 链,该链请求模型生成响应。

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

创建 RAG 服务

// 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}'],``]);

此常量文件存储了 LangChain 链的一些提示词。

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;` `};``}

该函数会创建一个链,该链可以在不依赖聊天历史记录的情况下提出问题。

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;`   `}` `}``}

RagService 服务非常简单。ask 方法将输入提交给链并输出响应。该方法从响应中提取内容,将聊天历史记录中人类和 AI 之间的聊天消息存储在内存中,并将对话返回给模板引擎进行渲染。

添加 RAG 控制器

import { IsNotEmpty, IsString } from 'class-validator';``   ``export class AskDto {` `@IsString()` `@IsNotEmpty()` `query: string;``}
@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);` `}``}

‍RAG 控制器将查询提交给链,获取结果,并将 HTML 代码发送回模板引擎进行渲染。

将模块导入 RAG 模块

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 {}

将 RagModule 导入 AppModule

import { RagTechBookModule } from '~rag-tech-book/rag-tech-book.module';``   ``@Module({` `imports: [`   `… other imports …`   `RagTechBookModule,` `],` `controllers: [AppController],``})``export class AppModule {}

修改应用控制器以渲染 Handlebar 模板

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

应用控制器通知 Handlebar 模板引擎渲染 index.hbs 文件。

HTMX 和 Handlebar 模板引擎

这是一个用于显示对话的简单界面。

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/htmx.org@2.0.1" 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>

以上是具有页眉、页脚和正文的默认布局。正文最终显示的是 AI 与人类之间的对话。页眉部分则导入 Tailwind,用于设置 HTML 元素的样式,并导入 HTMX 来与服务器交互。

<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>

用户可以在文本框中输入问题,然后点击 “发送” 按钮。该按钮向 /rag 发出 POST 请求并将对话附加到列表中。

这个 LangChain RAG 应用到此就创建完成了,创建该应用时采用了 Gemma 2 模型,以生成响应。

资源

欢迎您查阅 Github 代码库,以获取更多实用资源:

https://github.com/railsstudent/nestjs-gemma2-rag-app

如何系统的去学习大模型LLM ?

大模型时代,火爆出圈的LLM大模型让程序员们开始重新评估自己的本领。 “AI会取代那些行业?”“谁的饭碗又将不保了?”等问题热议不断。

事实上,抢你饭碗的不是AI,而是会利用AI的人。

科大讯飞、阿里、华为等巨头公司发布AI产品后,很多中小企业也陆续进场!超高年薪,挖掘AI大模型人才! 如今大厂老板们,也更倾向于会AI的人,普通程序员,还有应对的机会吗?

与其焦虑……

不如成为「掌握AI工具的技术人」,毕竟AI时代,谁先尝试,谁就能占得先机!

但是LLM相关的内容很多,现在网上的老课程老教材关于LLM又太少。所以现在小白入门就只能靠自学,学习成本和门槛很高。

针对所有自学遇到困难的同学们,我帮大家系统梳理大模型学习脉络,将这份 LLM大模型资料 分享出来:包括LLM大模型书籍、640套大模型行业报告、LLM大模型学习视频、LLM大模型学习路线、开源大模型学习教程等, 😝有需要的小伙伴,可以 扫描下方二维码领取🆓↓↓↓

👉CSDN大礼包🎁:全网最全《LLM大模型入门+进阶学习资源包》免费分享(安全链接,放心点击)👈

一、LLM大模型经典书籍

AI大模型已经成为了当今科技领域的一大热点,那以下这些大模型书籍就是非常不错的学习资源。

在这里插入图片描述

二、640套LLM大模型报告合集

这套包含640份报告的合集,涵盖了大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。(几乎涵盖所有行业)

在这里插入图片描述

三、LLM大模型系列视频教程

在这里插入图片描述

四、LLM大模型开源教程(LLaLA/Meta/chatglm/chatgpt)

在这里插入图片描述

LLM大模型学习路线

阶段1:AI大模型时代的基础理解

  • 目标:了解AI大模型的基本概念、发展历程和核心原理。

  • 内容

    • L1.1 人工智能简述与大模型起源
    • L1.2 大模型与通用人工智能
    • L1.3 GPT模型的发展历程
    • L1.4 模型工程
    • L1.4.1 知识大模型
    • L1.4.2 生产大模型
    • L1.4.3 模型工程方法论
    • L1.4.4 模型工程实践
    • L1.5 GPT应用案例

阶段2:AI大模型API应用开发工程

  • 目标:掌握AI大模型API的使用和开发,以及相关的编程技能。

  • 内容

    • L2.1 API接口
    • L2.1.1 OpenAI API接口
    • L2.1.2 Python接口接入
    • L2.1.3 BOT工具类框架
    • L2.1.4 代码示例
    • L2.2 Prompt框架
    • L2.3 流水线工程
    • L2.4 总结与展望

阶段3:AI大模型应用架构实践

  • 目标:深入理解AI大模型的应用架构,并能够进行私有化部署。

  • 内容

    • L3.1 Agent模型框架
    • L3.2 MetaGPT
    • L3.3 ChatGLM
    • L3.4 LLAMA
    • L3.5 其他大模型介绍

阶段4:AI大模型私有化部署

  • 目标:掌握多种AI大模型的私有化部署,包括多模态和特定领域模型。

  • 内容

    • L4.1 模型私有化部署概述
    • L4.2 模型私有化部署的关键技术
    • L4.3 模型私有化部署的实施步骤
    • L4.4 模型私有化部署的应用场景

这份 LLM大模型资料 包括LLM大模型书籍、640套大模型行业报告、LLM大模型学习视频、LLM大模型学习路线、开源大模型学习教程等, 😝有需要的小伙伴,可以 扫描下方二维码领取🆓↓↓↓

👉CSDN大礼包🎁:全网最全《LLM大模型入门+进阶学习资源包》免费分享(安全链接,放心点击)👈

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/881515.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.Net基础1

.NET框架 项目结构 Connected Services是第三方服务MVC框架appsettings.json配置文件Program.cs控制台应用程序Properties里的json文件是配置启动方式 1. 基本开发 出现这个bug是因为防火墙没有把浏览器加入白名单&#xff0c;可以暂时先用http启动代替 第一步创建控制器&am…

数字化AI新赋能,智享AI直播:开启一个全新的直播时代!

数字化AI新赋能&#xff0c;智享AI直播&#xff1a;开启一个全新的直播时代! 在科技日新月异的今天&#xff0c;人工智能&#xff08;AI&#xff09;技术正以前所未有的速度改变着我们的生活和工作方式。其中&#xff0c;AI直播技术的崛起&#xff0c;无疑是数字化时代的一大亮…

深入理解 C/C++ 指针

深入理解 C 指针&#xff1a;指针、解引用与指针变量的详细解析 前言 在 C 编程语言中&#xff0c;指针 是一个非常强大且重要的概念。对于初学者来说&#xff0c;指针往往会让人感到困惑不解。本文将通过形象的比喻&#xff0c;帮助大家深入理解指针、解引用与指针变量的概念…

ELK:Elasticsearch、Logstash、Kibana Spring Cloud Sleuth和Spring Cloud Zipkin

〇、虚拟机中docker安装elasticsearch 、Kibana、Logstash elasticsearch导入中文分词器 Logstash修改es数据库ip及创建索引名配置 一、elasticsearch数据库的结构 和mysql作比较&#xff0c;mysql中的数据库的二维表相当于es数据库的index索引结构&#xff1b;mysql数据库的二…

大数据处理从零开始————4.认识HDFS分布式文件系统

1.分布式文件系统HDFS 1.1 认识HDFS 当单台服务器的存储容量和计算性能已经无法处理大文件时&#xff0c;分布式文件系统应运而生。什么是分布式系统&#xff0c;分布式系统是由多个独立的计算机或节点组成的系统&#xff0c;这些计算机通过网络连接&#xff…

Mysql(五) --- 数据库设计

文章目录 前言1.范式1.1.第一范式1.1.1 定义1.1.2.例子 1.2.第二范式1.2.1 定义1.2.2 例子1.2.3.不满足第二范式可能会出现的问题 1.3.第三范式1.3.1 定义2.3.2 示例 2. 设计过程3. 实体-关系图3.1 E-R图的基本组成3.2 关系的类型3.2.1 一对一关系(1:1)3.2.2 ⼀对多关系(1:N)3.…

paimon,基础查询语句测试

基础设置 -- 创建catalog/加载catalog&#xff0c;如果这个catalog已经存在就不会创建&#xff0c;自动加载元数据信息CREATE CATALOG fs_paimon_catalog WITH ( type paimon, warehouse hdfs://wsl01:8020/paimon/catalog ); -- 使用catalog use catalog fs_paimon_catalog…

Java虚拟机(JVM)

目录 内存区域划分堆&#xff08;Heap&#xff09;方法区&#xff08;Method Area&#xff09;程序计数器&#xff08;Program Counter Register&#xff09;虚拟机栈&#xff08;VM Stack&#xff09;本地方法栈&#xff08;Native Method Stack&#xff09; 类加载的过程类加…

[C++]使用纯opencv部署yolov11-seg实例分割onnx模型

【算法介绍】 在C中使用纯OpenCV部署YOLOv11-seg进行实例分割是一项具有挑战性的任务&#xff0c;因为YOLOv11通常是用PyTorch等深度学习框架实现的&#xff0c;而OpenCV本身并不直接支持加载和运行PyTorch模型。然而&#xff0c;可以通过一些间接的方法来实现这一目标&#x…

运维工具之ansible

Ansible 1.什么是ansible? ​ ansible是基于ssh架构的自动化运维工具&#xff0c;由python语言实现&#xff0c;通过ansible可以远程批量部署等。 2.部署前提 ​ 控制端需要安装ansible,被控制端要开启ssh服务&#xff0c;并允许远程登录&#xff0c;被管理主机需要安装py…

卸载PLSQL及标准卸载流程

目录 1. 卸载PLSQL2. 删除注册表3. 删除数据信息 1. 卸载PLSQL 等待进度条走完 2. 删除注册表 regedit 右击删除 3. 删除数据信息 由于AppData是隐藏文件&#xff0c;需要勾选隐藏的项目。 重启电脑&#xff0c;PLSQL就卸载成功了。

浏览器和客户端结合的erp系统,java控制浏览器操作自动登录,socket客户端通信进行表单赋值

java做一个toB的客户端操作系统&#xff0c;客户端和web的结合&#xff1b; 主要是使用java编写客户端代码&#xff0c;采用selenium控制浏览器&#xff0c;主要是用到selenium自动化测试的功能&#xff1b; javaEE 项目调用 selenium使用谷歌控件chromedriver.exe控制浏览器…

使用Java调用OpenAI API并解析响应:详细教程

使用Java调用OpenAI API并解析响应&#xff1a;详细教程 在现代应用程序中&#xff0c;API调用是一个非常常见的任务。本文将通过一个完整的示例&#xff0c;讲解如何使用Java调用OpenAI的ChatGPT API&#xff0c;并通过ObjectMapper处理JSON响应。本文的示例不仅适用于OpenAI…

网络参考模型

OSI七层网络参考模型 OSI模型仅作为参考&#xff0c;现实中并不用&#xff0c;OSI模型的目的是为了解决主机之间的网络通讯。 1. 物理层&#xff1a; 物理层将由比特&#xff08;0和1&#xff09;组成的数据用不同的媒介&#xff08;电、光或其他形式的电磁波&#xff09;传输…

黑马软件测试第一篇_测试理论

概念 使用技术手段验证软件功能是否符合需求 测试种类 功能测试 自动化测试 接口测试 性能测试 按测试阶段划分 单元测试&#xff1a;针对程序源码进行测试 集成测试&#xff1a;又称接口测试&#xff0c;针对模块之间访问地址进行测试 系统测试&#xff1a;对整个系统进行…

京东零售数据湖应用与实践

作者&#xff1a;陈洪健&#xff1a;京东零售大数据架构师&#xff0c;深耕大数据 10 年&#xff0c;2019 年加入京东&#xff0c;主要负责 OLAP 优化、大数据传输工具生态、流批一体、SRE 建设。 当前企业数据处理广泛采用 Lambda 架构。Lambda 架构的优点是保证了数据的完整性…

YOLO的相关改进机制

我的面包多平台有多种关于YOLO的改进&#xff0c;大家尽早关注&#xff0c;不迷路

【宽字节注入】

字符编码 url 编码 GBK编码 utf8 编码 宽字节注入 php中的转译函数 宽字节注入介绍 练习 正常输入没有回显&#xff1a; 没有回显 usernameadmin&passwordadmin 闭合单引号&#xff0c;依旧没有回显 usernameadmin and 11%23&passwordadmin利用宽字节尝试闭合,依旧…

查看SQL Server授权序列号通过SQL查询查看安装日志文件使用PowerShell查询

本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯 转载说明:务必注明来源(注明:作者:王文峰…

在Stable Diffusion WebUI中安装SadTalker插件时几种错误提示的处理方法

SD中的插件一般安装比较简单&#xff0c;但也有一些插件安装会比较难。比如我在安装SadTalker时&#xff0c;就遇到很多问题&#xff0c;一度放弃了&#xff0c;后来查了一些网上攻略&#xff0c;自己也反复查看日志&#xff0c;终于解决&#xff0c;不吐不快。 一、在Stable …