Untitled
unknown
javascript
14 days ago
10 kB
3
Indexable
Never
import { pull } from "langchain/hub"; import { formatDocumentsAsString } from "langchain/util/document"; import { createStuffDocumentsChain } from "langchain/chains/combine_documents"; import { ChatPromptTemplate, HumanMessagePromptTemplate, PromptTemplate, SystemMessagePromptTemplate, } from "@langchain/core/prompts"; import { RecursiveCharacterTextSplitter } from "langchain/text_splitter"; import { ChatOpenAI, OpenAIEmbeddings } from "@langchain/openai"; import { Injectable, Logger, OnModuleInit } from "@nestjs/common"; import { StringOutputParser } from "@langchain/core/output_parsers"; import { Runnable, RunnablePassthrough, RunnableSequence } from "@langchain/core/runnables"; import { UnstructuredLoader } from "@langchain/community/document_loaders/fs/unstructured"; import { MemoryVectorStore } from "langchain/vectorstores/memory"; import { ChatAnthropic } from "@langchain/anthropic"; import { VectorStoreRetriever } from "@langchain/core/vectorstores"; @Injectable() export class ChatService implements OnModuleInit { constructor() {} private retriever: VectorStoreRetriever; private logger = new Logger(ChatService.name); private systemPrompt = ` # Character - Đóng vai là một chuyên gia, bác sĩ tư vấn thẩm mĩ, da liễu có khả năng phân tích và trả lời các câu hỏi dựa trên dữ liệu về sản phẩm, quy trình và các liệu pháp điều trị thẫm mĩ hoặc giải đáp những thắc mắc về da, trị liệu,... - Niềm nở, thân thiện tư vấn đề các vấn đề gặp phải. - Không dùng các từ rất tiếc, xin lỗi và nói về các thông tin bị thiếu trong thông tin được cung cấp. - Từ ngữ rành mạch, dễ hiểu. ## Skills: ### Skill 1: Đưa được ra các liệu trình phù hợp, kết hợp các ưu đãi từ công ty, với ngôn từ tự nhiên, gần gũi, dễ hiểu. - Dựa vào các thông tin được thêm trong các file liên quan về liệu trình, ưu đãi ### Skill 2: Tóm tắt được kết quả sau khi thực hiện liệu trình, dự đoán sẽ có kết quả trong bao lâu - Dựa vào các thông tin được thêm trong các file liên quan về liệu trình ### Skill 3: Giải thích tại sao chọn liệu trình đó, đưa ra một checklist chi tiết và có đánh số thứ tự rõ ràng - Dựa vào các thông tin được thêm trong các file liên quan về liệu trình, checklist, sản phẩm ### Skill 4: Làm rõ được tần xuất sử dụng các sản phẩm liên quan, tóm tắt thành bảng báo giá chi tiết cụ thể - Dựa vào các thông tin được thêm trong các file liên quan sản phẩm, liệu trình, giá cả ### Skill 5: Đưa ra được các thông tin cần thiết từ những câu hỏi sử dụng vốn hiểu biết về thẩm mĩ - Dựa vào các thông tin được thêm trong các file liên quan sản phẩm, liệu trình, giá cả ## Constraints: - Viết chi tiết khoảng 8000 từ để có thể đưa ra được các liệu trình phù hợp, kết hợp các ưu đãi mới nhất từ công ty, với ngôn từ tự nhiên, gần gũi, dễ hiểu, có tóm tắt kết quả trước, sẽ có kết quả sau bao lâu. Giải thích tại sao lựa chọn liệu trình này và đưa ra 1 checklist chi tiết, trong đó có đánh số thứ tự. Làm rõ tần suất sử dụng, tóm tắt thành bảng báo giá chi tiết, tất cả được làm trên một artifact. - Không dùng các mã code không phù hợp vì đối tượng khách hàng đọc sẽ không hiểu. - Kết quả hiển thị theo dạng markdown đẹp, có cấu trúc, phù hợp. `; private humanPrompt = ` Context information is below: {context} Given the context information, answer the query: Query: {question} Note: - Đưa ra câu trả lời chi tiết theo dạng markdown để hiện thị cho dễ. - Câu hỏi nếu đề cập đến một người, cá nhân khác thì trả lời với tư cách giải đáp yêu cầu cho người đó. - Câu hỏi có liên quan đến vấn đề về da hoặc muốn tư vấn sản phẩm, liệu trình thì viết chi tiết đưa ra thông tin cho người dùng. - Sau đó, đề xuất 1-3 câu hỏi để người dùng có thể hỏi lại dựa trên câu trả lời trước đó. (answer) ### Câu hỏi recommend: - (recommend_question_1) - (recommend_question_2) - (recommend_question_3) `; async onModuleInit() { // Load documents from various sources, including Markdown const markdownPath1 = "./md/current-spa-promotions.md"; const markdownPath2 = "./md/detailed-skincare-consultation-example.md"; const markdownPath3 = "./md/detailed-skincare-routine-guide.md"; const markdownPath4 = "./md/spa-consultation-skills.md"; const markdownPath5 = "./md/spa-product-database.md"; const markdownPath6 = "./md/spa-skincare-knowledge-part1.md"; const markdownPath7 = "./md/spa-skincare-knowledge-part2.md"; const markdownPath8 = "./md/spa-skincare-knowledge-part3.md"; const markdownPath9 = "./md/spa-treatment-database.md"; const loaders = [ new UnstructuredLoader(markdownPath1, { apiKey: process.env.UNSTRUCTURED_API_KEY, apiUrl: process.env.UNSTRUCTURED_API_URL, }), new UnstructuredLoader(markdownPath2, { apiKey: process.env.UNSTRUCTURED_API_KEY, apiUrl: process.env.UNSTRUCTURED_API_URL, }), new UnstructuredLoader(markdownPath3, { apiKey: process.env.UNSTRUCTURED_API_KEY, apiUrl: process.env.UNSTRUCTURED_API_URL, }), new UnstructuredLoader(markdownPath4, { apiKey: process.env.UNSTRUCTURED_API_KEY, apiUrl: process.env.UNSTRUCTURED_API_URL, }), new UnstructuredLoader(markdownPath5, { apiKey: process.env.UNSTRUCTURED_API_KEY, apiUrl: process.env.UNSTRUCTURED_API_URL, }), new UnstructuredLoader(markdownPath6, { apiKey: process.env.UNSTRUCTURED_API_KEY, apiUrl: process.env.UNSTRUCTURED_API_URL, }), new UnstructuredLoader(markdownPath7, { apiKey: process.env.UNSTRUCTURED_API_KEY, apiUrl: process.env.UNSTRUCTURED_API_URL, }), new UnstructuredLoader(markdownPath8, { apiKey: process.env.UNSTRUCTURED_API_KEY, apiUrl: process.env.UNSTRUCTURED_API_URL, }), new UnstructuredLoader(markdownPath9, { apiKey: process.env.UNSTRUCTURED_API_KEY, apiUrl: process.env.UNSTRUCTURED_API_URL, }), ]; // Load and concatenate all documents const docs = []; for (const loader of loaders) { const loadedDocs = await loader.load(); docs.push(...loadedDocs); } const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 1000, chunkOverlap: 200, }); const splits = await textSplitter.splitDocuments(docs); const vectorStore = await MemoryVectorStore.fromDocuments(splits, new OpenAIEmbeddings()); // Retrieve and generate using the relevant snippets of the blog. this.retriever = vectorStore.asRetriever(); this.logger.log("success loader file md"); } async *ask(params) { const { question } = params; const llm = new ChatAnthropic({ model: "claude-3-5-sonnet-20240620", temperature: 0, maxTokens: 8192, }); const systemPrompt = this.systemPrompt; const humanPrompt = this.humanPrompt; const systemMessagePrompt = SystemMessagePromptTemplate.fromTemplate(systemPrompt); const humanMessagePrompt = HumanMessagePromptTemplate.fromTemplate(humanPrompt); const chatPrompt = ChatPromptTemplate.fromMessages([systemMessagePrompt, humanMessagePrompt]); // Custom runnable to log context const logContextRunnable = async (input) => { console.log("Context:", input.context); return input; }; const declarativeRagChain: RunnableSequence = RunnableSequence.from([ { context: this.retriever.pipe(formatDocumentsAsString), question: new RunnablePassthrough(), }, logContextRunnable, chatPrompt, llm, new StringOutputParser(), ]); let response = ""; for await (const chunk of await declarativeRagChain.stream(question)) { yield chunk.toString(); response += chunk.toString(); } } async askDebug(params) { const { question } = params; const llm = new ChatAnthropic({ model: "claude-3-5-sonnet-20240620", temperature: 0.25, maxTokens: 8192, }); const systemPrompt = this.systemPrompt; const humanPrompt = this.humanPrompt; const systemMessagePrompt = SystemMessagePromptTemplate.fromTemplate(systemPrompt); const humanMessagePrompt = HumanMessagePromptTemplate.fromTemplate(humanPrompt); const chatPrompt = ChatPromptTemplate.fromMessages([systemMessagePrompt, humanMessagePrompt]); /* context: async (input) => { const relevantDocs = await this.retriever._getRelevantDocuments(input.question); return relevantDocs.map((doc) => doc.pageContent).join("\n\n"); }, */ const declarativeRagChain: RunnableSequence = RunnableSequence.from([ { context: this.retriever.pipe(formatDocumentsAsString), question: new RunnablePassthrough(), }, chatPrompt, llm, new StringOutputParser(), ]); const res = await declarativeRagChain.invoke(question); return res; } }
Leave a Comment