diff --git a/README.md b/README.md index 4a3b9cf3..233825e2 100644 --- a/README.md +++ b/README.md @@ -196,7 +196,6 @@ Dialoqbase nothing without the support of our wonderful sponsors. If you are int - And many more wonderful supporters from [Ko-fi](https://ko-fi.com/n4ze3m). diff --git a/app/ui/package.json b/app/ui/package.json index 73d2544c..d5091283 100644 --- a/app/ui/package.json +++ b/app/ui/package.json @@ -1,7 +1,7 @@ { "name": "app", "private": true, - "version": "1.8.2", + "version": "1.8.3", "type": "module", "scripts": { "dev": "vite", diff --git a/app/ui/src/@types/bot.ts b/app/ui/src/@types/bot.ts index 3cc8b6b9..ff342c41 100644 --- a/app/ui/src/@types/bot.ts +++ b/app/ui/src/@types/bot.ts @@ -5,7 +5,7 @@ export type BotSettings = { model: string; public_id: string; temperature: number; - embedding: string; + embedding: string; noOfDocumentsToRetrieve: number; qaPrompt: string; questionGeneratorPrompt: string; @@ -15,6 +15,8 @@ export type BotSettings = { bot_protect: boolean; use_rag: boolean; bot_model_api_key: string; + noOfChatHistoryInContext: number; + semanticSearchSimilarityScore: string }, chatModel: { label: string; diff --git a/app/ui/src/components/Bot/Settings/SettingsCard.tsx b/app/ui/src/components/Bot/Settings/SettingsCard.tsx index 10d717e6..49503a8d 100644 --- a/app/ui/src/components/Bot/Settings/SettingsCard.tsx +++ b/app/ui/src/components/Bot/Settings/SettingsCard.tsx @@ -164,6 +164,8 @@ export const SettingsCard: React.FC = ({ use_rag: data.use_rag, bot_model_api_key: data.bot_model_api_key, noOfDocumentsToRetrieve: data.noOfDocumentsToRetrieve, + noOfChatHistoryInContext: data.noOfChatHistoryInContext, + semanticSearchSimilarityScore: data.semanticSearchSimilarityScore, }} form={form} requiredMark={false} @@ -297,6 +299,52 @@ export const SettingsCard: React.FC = ({ placeholder="Enter number of documents to retrieve" /> + {/* + + */} + + - - - - + )} @@ -226,7 +220,7 @@ export const LLMForm: React.FC = ({ setOpenAddModel }) => { rules={[ { required: true, - message: `Please your ${providerName[apiType]} API Key`, + message: `Please enter ${providerName[apiType]} API Key`, }, ]} > @@ -268,6 +262,18 @@ export const LLMForm: React.FC = ({ setOpenAddModel }) => { label: "OpenRouter", value: "openrouter", }, + { + label: "OpenAI", + value: "openai-api", + }, + { + label: "Google", + value: "google", + }, + { + label: "Anthropic", + value: "anthropic", + }, ]} /> @@ -277,7 +283,7 @@ export const LLMForm: React.FC = ({ setOpenAddModel }) => { disabled={isSaveModel} className="flex w-full justify-center rounded-md border border-transparent bg-indigo-600 py-2 px-4 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2" > - {apiType === "replicate" + {noFetchProviders.includes(apiType) ? !isSaveLocalModel ? "Save Model" : "Saving Model..." diff --git a/package.json b/package.json index 57fbded1..298daa3a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dialoqbase", - "version": "1.8.2", + "version": "1.8.3", "description": "Create chatbots with ease", "scripts": { "ui:dev": "pnpm run --filter ui dev", diff --git a/server/package.json b/server/package.json index 80c9fdbd..1e5bb1df 100644 --- a/server/package.json +++ b/server/package.json @@ -45,7 +45,6 @@ "@langchain/cohere": "^0.0.6", "@langchain/community": "^0.0.35", "@langchain/google-genai": "^0.0.10", - "@langchain/groq": "^0.0.3", "@langchain/openai": "^0.0.18", "@prisma/client": "^5.9.1", "@slack/bolt": "^3.13.2", @@ -81,6 +80,7 @@ "replicate": "^0.26.0", "sitemapper": "^3.2.6", "ts-node": "^10.9.1", + "turndown": "^7.1.3", "unique-names-generator": "^4.7.1", "wavefile": "^11.0.0", "yt-transcript": "^0.0.2", @@ -91,6 +91,7 @@ "@types/node": "20.4.4", "@types/pubsub-js": "^1.8.3", "@types/tap": "^15.0.5", + "@types/turndown": "^5.0.4", "c8": "9.0.0", "fastify-tsconfig": "2.0.0", "prisma": "^5.9.1", diff --git a/server/prisma/migrations/q_27/migration.sql b/server/prisma/migrations/q_27/migration.sql new file mode 100644 index 00000000..0da6bd7b --- /dev/null +++ b/server/prisma/migrations/q_27/migration.sql @@ -0,0 +1,3 @@ +-- AlterTable +ALTER TABLE "Bot" ADD COLUMN "noOfChatHistoryInContext" INTEGER DEFAULT 15, +ADD COLUMN "semanticSearchSimilarityScore" TEXT DEFAULT 'none'; diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma index 65929218..6a99a300 100644 --- a/server/prisma/schema.prisma +++ b/server/prisma/schema.prisma @@ -10,38 +10,40 @@ datasource db { } model Bot { - id String @id @default(cuid()) - publicId String @unique @default(uuid()) - name String - user_id Int? - User User? @relation(fields: [user_id], references: [user_id]) - description String? - createdAt DateTime @default(now()) - temperature Float @default(0.7) - noOfDocumentsToRetrieve Int? @default(4) - model String @default("gpt-3.5-turbo") - provider String @default("openai") - embedding String @default("openai") - streaming Boolean @default(false) - showRef Boolean @default(false) - questionGeneratorPrompt String @default("Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question. Chat History: {chat_history} Follow Up Input: {question} Standalone question:") - qaPrompt String @default("You are a helpful AI assistant. Use the following pieces of context to answer the question at the end. If you don't know the answer, just say you don't know. DO NOT try to make up an answer. If the question is not related to the context, politely respond that you are tuned to only answer questions that are related to the context. {context} Question: {question} Helpful answer in markdown:") - voice_to_text_type String @default("web_api") - text_to_voice_enabled Boolean @default(false) - text_to_voice_type String @default("web_api") - text_to_voice_type_metadata Json @default("{}") @db.Json - use_hybrid_search Boolean @default(false) - haveDataSourcesBeenAdded Boolean @default(false) - use_rag Boolean @default(false) - bot_protect Boolean @default(false) - bot_api_key String? - bot_model_api_key String? - options Json? @default("{}") @db.Json - BotAppearance BotAppearance[] - document BotDocument[] - BotIntegration BotIntegration[] - BotPlayground BotPlayground[] - source BotSource[] + id String @id @default(cuid()) + publicId String @unique @default(uuid()) + name String + user_id Int? + User User? @relation(fields: [user_id], references: [user_id]) + description String? + createdAt DateTime @default(now()) + temperature Float @default(0.7) + noOfDocumentsToRetrieve Int? @default(4) + noOfChatHistoryInContext Int? @default(15) + semanticSearchSimilarityScore String? @default("none") + model String @default("gpt-3.5-turbo") + provider String @default("openai") + embedding String @default("openai") + streaming Boolean @default(false) + showRef Boolean @default(false) + questionGeneratorPrompt String @default("Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question. Chat History: {chat_history} Follow Up Input: {question} Standalone question:") + qaPrompt String @default("You are a helpful AI assistant. Use the following pieces of context to answer the question at the end. If you don't know the answer, just say you don't know. DO NOT try to make up an answer. If the question is not related to the context, politely respond that you are tuned to only answer questions that are related to the context. {context} Question: {question} Helpful answer in markdown:") + voice_to_text_type String @default("web_api") + text_to_voice_enabled Boolean @default(false) + text_to_voice_type String @default("web_api") + text_to_voice_type_metadata Json @default("{}") @db.Json + use_hybrid_search Boolean @default(false) + haveDataSourcesBeenAdded Boolean @default(false) + use_rag Boolean @default(false) + bot_protect Boolean @default(false) + bot_api_key String? + bot_model_api_key String? + options Json? @default("{}") @db.Json + BotAppearance BotAppearance[] + document BotDocument[] + BotIntegration BotIntegration[] + BotPlayground BotPlayground[] + source BotSource[] } model BotSource { @@ -96,7 +98,7 @@ model DialoqbaseSettings { hideDefaultModels Boolean? @default(false) defaultChatModel String @default("gpt-3.5-turbo-dbase") defaultEmbeddingModel String @default("dialoqbase_eb_text-embedding-ada-002") - ollamaURL String? @default("http://host.docker.internal:11434") + ollamaURL String? @default("http://host.docker.internal:11434") } model BotIntegration { diff --git a/server/prisma/seed.ts b/server/prisma/seed.ts index bc814ae8..5f1505e2 100644 --- a/server/prisma/seed.ts +++ b/server/prisma/seed.ts @@ -347,6 +347,14 @@ const LLMS: { stream_available: true, model_provider: "Groq", }, + { + model_id: "gpt-4o-dbase", + name: "GPT-4o (OpenAI)", + model_type: "chat", + stream_available: true, + model_provider: "OpenAI", + config: "{}", + } ]; const EMBEDDING_MODELS: { diff --git a/server/src/handlers/api/v1/admin/model.handler.ts b/server/src/handlers/api/v1/admin/model.handler.ts index 04dee394..04c9fb07 100644 --- a/server/src/handlers/api/v1/admin/model.handler.ts +++ b/server/src/handlers/api/v1/admin/model.handler.ts @@ -1,5 +1,3 @@ -// this the dedicated file for the model handler for the admin route -// why i do this? because i want to make the code more readable and easy to maintain import { FastifyReply, FastifyRequest } from "fastify"; import { FetchModelFromInputedUrlRequest, @@ -7,125 +5,15 @@ import { SaveModelFromInputedUrlRequest, ToogleModelRequest, } from "./type"; -import axios from "axios"; import { removeTrailingSlash } from "../../../../utils/url"; import { getSettings } from "../../../../utils/common"; - -const _getModelFromUrl = async (url: string, apiKey?: string) => { - try { - const response = await axios.get(`${url}/models`, { - headers: { - "HTTP-Referer": - process.env.LOCAL_REFER_URL || "https://dialoqbase.n4ze3m.com/", - "X-Title": process.env.LOCAL_TITLE || "Dialoqbase", - Authorization: apiKey && `Bearer ${apiKey}`, - }, - }); - return response.data; - } catch (error) { - console.error(error); - return null; - } -}; - -const _getOllamaModels = async (url: string) => { - try { - const response = await axios.get(`${url}/api/tags`); - const { models } = response.data as { - models: { - name: string; - }[]; - }; - return models.map((data) => { - return { - id: data.name, - object: data.name, - }; - }); - } catch (error) { - return null; - } -}; - -const _isReplicateModelExist = async (model_id: string, token: string) => { - try { - const url = "https://api.replicate.com/v1/models/"; - const isVersionModel = model_id.split(":").length > 1; - if (!isVersionModel) { - const res = await axios.get(`${url}${model_id}`, { - headers: { - Authorization: `Token ${token}`, - }, - }); - const data = res.data; - return { - success: true, - message: "Model found", - name: data.name, - }; - } else { - const [owner, model_name] = model_id.split("/"); - const version = model_name.split(":")[1]; - const res = await axios.get( - `${url}${owner}/${model_name.split(":")[0]}/versions/${version}`, - { - headers: { - Authorization: `Token ${token}`, - }, - } - ); - - const data = res.data; - - return { - success: true, - message: "Model found", - name: data.name, - }; - } - } catch (error) { - if (axios.isAxiosError(error)) { - console.error(error.response?.data); - if (error.response?.status === 404) { - return { - success: false, - message: "Model not found", - name: undefined, - }; - } else if (error.response?.status === 401) { - return { - success: false, - message: "Unauthorized", - name: undefined, - }; - } else if (error.response?.status === 403) { - return { - success: false, - message: "Forbidden", - name: undefined, - }; - } else if (error.response?.status === 500) { - return { - success: false, - message: "Internal Server Error", - name: undefined, - }; - } else { - return { - success: false, - message: "Internal Server Error", - name: undefined, - }; - } - } else { - return { - success: false, - message: "Internal Server Error", - name: undefined, - }; - } - } -}; +import { + getModelFromUrl, + getOllamaModels, + isReplicateModelExist, + isValidModel, + modelProvider, +} from "./utils"; export const getAllModelsHandler = async ( request: FastifyRequest, @@ -143,7 +31,7 @@ export const getAllModelsHandler = async ( const settings = await getSettings(prisma); const not_to_hide_providers = settings?.hideDefaultModels - ? [ "Local", "local", "ollama", "transformer", "Transformer"] + ? ["Local", "local", "ollama", "transformer", "Transformer"] : undefined; const allModels = await prisma.dialoqbaseModels.findMany({ where: { @@ -180,7 +68,7 @@ export const fetchModelFromInputedUrlHandler = async ( } if (api_type === "ollama") { - const models = await _getOllamaModels(removeTrailingSlash(ollama_url!)); + const models = await getOllamaModels(removeTrailingSlash(ollama_url!)); if (!models) { return reply.status(404).send({ @@ -193,7 +81,7 @@ export const fetchModelFromInputedUrlHandler = async ( data: models, }; } else if (api_type === "openai") { - const model = await _getModelFromUrl(removeTrailingSlash(url!), api_key); + const model = await getModelFromUrl(removeTrailingSlash(url!), api_key); if (!model) { return reply.status(404).send({ @@ -205,6 +93,10 @@ export const fetchModelFromInputedUrlHandler = async ( return { data: Array.isArray(model) ? model : model.data, }; + } else { + return reply.status(400).send({ + message: "Invalid api type", + }); } } catch (error) { console.error(error); @@ -232,7 +124,7 @@ export const saveModelFromInputedUrlHandler = async ( request.body; if (api_type === "replicate") { - const isModelExist = await _isReplicateModelExist(model_id, api_key!); + const isModelExist = await isReplicateModelExist(model_id, api_key!); if (!isModelExist.success) { return reply.status(404).send({ @@ -269,6 +161,37 @@ export const saveModelFromInputedUrlHandler = async ( }, }); + return { + message: "success", + }; + } else if ( + api_type === "openai-api" || + api_type === "google" || + api_type === "anthropic" || + api_type === "groq" + ) { + const provider = modelProvider[api_type]; + console.log(provider, "provider"); + const validModel = await isValidModel(model_id.trim(), provider); + + if (!validModel) { + return reply.status(404).send({ + message: `Model not found for the given model_id ${model_id}`, + }); + } + + let newModelId = model_id.trim() + `_dialoqbase_${new Date().getTime()}`; + + await prisma.dialoqbaseModels.create({ + data: { + name: name, + model_id: newModelId, + stream_available: true, + local_model: true, + model_provider: provider, + }, + }); + return { message: "success", }; diff --git a/server/src/handlers/api/v1/admin/type.ts b/server/src/handlers/api/v1/admin/type.ts index 6d627f54..904b50b3 100644 --- a/server/src/handlers/api/v1/admin/type.ts +++ b/server/src/handlers/api/v1/admin/type.ts @@ -37,7 +37,15 @@ export type SaveModelFromInputedUrlRequest = { name: string; stream_available: boolean; api_key?: string; - api_type: "openai" | "ollama" | "replicate"; + api_type: + | "openai" + | "ollama" + | "replicate" + | "openai-api" + | "google" + | "anthropic" + | "groq" + ; }; }; diff --git a/server/src/handlers/api/v1/admin/utils.ts b/server/src/handlers/api/v1/admin/utils.ts new file mode 100644 index 00000000..9d22ba00 --- /dev/null +++ b/server/src/handlers/api/v1/admin/utils.ts @@ -0,0 +1,142 @@ +import axios from "axios"; +import { chatModelProvider } from "../../../../utils/models"; + +export const isReplicateModelExist = async ( + model_id: string, + token: string +) => { + try { + const url = "https://api.replicate.com/v1/models/"; + const isVersionModel = model_id.split(":").length > 1; + if (!isVersionModel) { + const res = await axios.get(`${url}${model_id}`, { + headers: { + Authorization: `Token ${token}`, + }, + }); + const data = res.data; + return { + success: true, + message: "Model found", + name: data.name, + }; + } else { + const [owner, model_name] = model_id.split("/"); + const version = model_name.split(":")[1]; + const res = await axios.get( + `${url}${owner}/${model_name.split(":")[0]}/versions/${version}`, + { + headers: { + Authorization: `Token ${token}`, + }, + } + ); + + const data = res.data; + + return { + success: true, + message: "Model found", + name: data.name, + }; + } + } catch (error) { + if (axios.isAxiosError(error)) { + console.error(error.response?.data); + if (error.response?.status === 404) { + return { + success: false, + message: "Model not found", + name: undefined, + }; + } else if (error.response?.status === 401) { + return { + success: false, + message: "Unauthorized", + name: undefined, + }; + } else if (error.response?.status === 403) { + return { + success: false, + message: "Forbidden", + name: undefined, + }; + } else if (error.response?.status === 500) { + return { + success: false, + message: "Internal Server Error", + name: undefined, + }; + } else { + return { + success: false, + message: "Internal Server Error", + name: undefined, + }; + } + } else { + return { + success: false, + message: "Internal Server Error", + name: undefined, + }; + } + } +}; + +export const getModelFromUrl = async (url: string, apiKey?: string) => { + try { + const response = await axios.get(`${url}/models`, { + headers: { + "HTTP-Referer": + process.env.LOCAL_REFER_URL || "https://dialoqbase.n4ze3m.com/", + "X-Title": process.env.LOCAL_TITLE || "Dialoqbase", + Authorization: apiKey && `Bearer ${apiKey}`, + }, + }); + return response.data; + } catch (error) { + console.error(error); + return null; + } +}; + +export const getOllamaModels = async (url: string) => { + try { + const response = await axios.get(`${url}/api/tags`); + const { models } = response.data as { + models: { + name: string; + }[]; + }; + return models.map((data) => { + return { + id: data.name, + object: data.name, + }; + }); + } catch (error) { + return null; + } +}; + +export const modelProvider = { + "openai-api": "OpenAI", + anthropic: "Anthropic", + google: "Google", + groq: "Groq", +}; + +export const isValidModel = async ( + model_id: string, + model_provider: string +) => { + try { + const model = chatModelProvider(model_provider, model_id, 0.7, {}); + const chat = await model.invoke("Hello"); + return chat !== null; + } catch (error) { + console.error(error); + return false; + } +}; diff --git a/server/src/loader/web.ts b/server/src/loader/web.ts index 78d4f713..25620647 100644 --- a/server/src/loader/web.ts +++ b/server/src/loader/web.ts @@ -1,6 +1,6 @@ import { BaseDocumentLoader } from "langchain/document_loaders/base"; import { Document } from "langchain/document"; -import { compile } from "html-to-text"; +import { websiteParser } from "../utils/website-parser"; export interface WebLoaderParams { url: string; @@ -24,10 +24,7 @@ export class DialoqbaseWebLoader async load(): Promise>[]> { const html = await this._fetchHTML(); - const htmlCompiler = compile({ - wordwrap: false, - }); - const text = htmlCompiler(html); + const text = websiteParser(html); const metadata = { source: this.url }; return [new Document({ pageContent: text, metadata })]; } diff --git a/server/src/utils/models.ts b/server/src/utils/models.ts index 0037b00e..ee1fb64e 100644 --- a/server/src/utils/models.ts +++ b/server/src/utils/models.ts @@ -7,7 +7,6 @@ import { OpenAI } from "@langchain/openai"; import { ChatGoogleGenerativeAI } from "@langchain/google-genai"; import { ChatOllama } from "@langchain/community/chat_models/ollama"; import { Replicate } from "@langchain/community/llms/replicate"; -import { ChatGroq } from "@langchain/groq"; export const chatModelProvider = ( provider: string, @@ -100,10 +99,14 @@ export const chatModelProvider = ( ...otherFields, }); case "groq": - return new ChatGroq({ - model: modelName, - temperature: temperature, + return new ChatOpenAI({ + modelName: modelName, + openAIApiKey: process.env.GROQ_API_KEY! || "", ...otherFields, + configuration: { + baseURL: "https://api.groq.com/openai/v1", + apiKey: process.env.GROQ_API_KEY! || "", + }, }); default: console.log("using default"); diff --git a/server/src/utils/store.ts b/server/src/utils/store.ts index c104fd43..33bce9c3 100644 --- a/server/src/utils/store.ts +++ b/server/src/utils/store.ts @@ -94,8 +94,10 @@ export class DialoqbaseVectorStore extends VectorStore { k: number, filter?: this["FilterType"] | undefined ): Promise<[Document>, number][]> { - console.log(this.botId); - const vector = `[${query.join(",")}]`; + if (!query) { + return []; + } + const vector = `[${query?.join(",")}]`; const bot_id = this.botId; const botInfo = await prisma.bot.findFirst({ @@ -106,10 +108,13 @@ export class DialoqbaseVectorStore extends VectorStore { const match_count = botInfo?.noOfDocumentsToRetrieve || k; + const semanticSearchSimilarityScore = + botInfo?.semanticSearchSimilarityScore || "none"; + const data = await prisma.$queryRaw` SELECT * FROM "similarity_search_v2"(query_embedding := ${vector}::vector, botId := ${bot_id}::text,match_count := ${match_count}::int) `; - + const result: [Document, number][] = ( data as SearchEmbeddingsResponse[] ).map((resp) => [ @@ -119,7 +124,16 @@ export class DialoqbaseVectorStore extends VectorStore { }), resp.similarity, ]); - return result; + + if (semanticSearchSimilarityScore === "none") { + return result; + } + + const valueInFloat = parseFloat(semanticSearchSimilarityScore); + const filteredResult = result.filter( + ([, similarity]) => similarity >= valueInFloat + ); + return filteredResult; } _vectorstoreType(): string { diff --git a/server/src/utils/website-parser.ts b/server/src/utils/website-parser.ts new file mode 100644 index 00000000..e7498f0d --- /dev/null +++ b/server/src/utils/website-parser.ts @@ -0,0 +1,10 @@ +import * as cheerio from "cheerio"; +import TurndownService from "turndown"; +let turndownService = new TurndownService(); + +export const websiteParser = (html: string) => { + const $ = cheerio.load(html); + const mainContent = $('[role="main"]').html() || $("main").html() || $.html(); + const markdown = turndownService.turndown(mainContent); + return markdown; +}; diff --git a/server/yarn.lock b/server/yarn.lock index 039f02f0..24dcfdb2 100644 --- a/server/yarn.lock +++ b/server/yarn.lock @@ -738,7 +738,7 @@ uuid "^9.0.0" zod "^3.22.3" -"@langchain/core@0.1.43", "@langchain/core@~0.1", "@langchain/core@~0.1.13", "@langchain/core@~0.1.36", "@langchain/core@~0.1.41", "@langchain/core@~0.1.5": +"@langchain/core@0.1.43", "@langchain/core@~0.1", "@langchain/core@~0.1.36", "@langchain/core@~0.1.41", "@langchain/core@~0.1.5": version "0.1.43" resolved "https://registry.yarnpkg.com/@langchain/core/-/core-0.1.43.tgz#2d0af42817f8d431bba5252b2ff667a9cb3a25e5" integrity sha512-owE+UU38e4TsUq5yoaKCF+ag6u0ppwgdaqEt2Q57pdcr9nEcy8/PgTunxB10Vksq4fTJgnwWEYf/wMGZnFlRow== @@ -763,26 +763,6 @@ "@google/generative-ai" "^0.1.3" "@langchain/core" "~0.1.5" -"@langchain/groq@^0.0.3": - version "0.0.3" - resolved "https://registry.yarnpkg.com/@langchain/groq/-/groq-0.0.3.tgz#0f890501e308d86b2ccc08be4bbe4591d697dd3a" - integrity sha512-VJc0madTIsTr+bu/RXHg3ZN0TuUdunESNh39TtctrS/mJvgQXOCA1GDe5kTqv5naegFJh4oO3noR+4DbfDtrUA== - dependencies: - "@langchain/core" "~0.1" - "@langchain/openai" "^0.0.14" - groq-sdk "^0.3.0" - -"@langchain/openai@^0.0.14": - version "0.0.14" - resolved "https://registry.yarnpkg.com/@langchain/openai/-/openai-0.0.14.tgz#27a6ba83f6b754391868b22f3b90cd440038acf0" - integrity sha512-co6nRylPrLGY/C3JYxhHt6cxLq07P086O7K3QaZH7SFFErIN9wSzJonpvhZR07DEUq6eK6wKgh2ORxA/NcjSRQ== - dependencies: - "@langchain/core" "~0.1.13" - js-tiktoken "^1.0.7" - openai "^4.26.0" - zod "^3.22.4" - zod-to-json-schema "^3.22.3" - "@langchain/openai@^0.0.18", "@langchain/openai@~0.0.14": version "0.0.18" resolved "https://registry.yarnpkg.com/@langchain/openai/-/openai-0.0.18.tgz#57db3984a82424bbedc94925c3f9b629458ea519" @@ -1394,6 +1374,11 @@ resolved "https://registry.yarnpkg.com/@types/tsscmp/-/tsscmp-1.0.0.tgz#761c885a530f9673ae6fda0cae38253ffd46cba6" integrity sha512-rj18XR6c4Ohds86Lq8MI1NMRrXes4eLo4H06e5bJyKucE1rXGsfBBbFGD2oDC+DSufQCpnU3TTW7QAiwLx+7Yw== +"@types/turndown@^5.0.4": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@types/turndown/-/turndown-5.0.4.tgz#61fcdda2e539a86b1d40cb3277505f22ca76f014" + integrity sha512-28GI33lCCkU4SGH1GvjDhFgOVr+Tym4PXGBIU1buJUa6xQolniPArtUT+kv42RR2N9MsMLInkr904Aq+ESHBJg== + "@types/uuid@^9.0.1": version "9.0.8" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba" @@ -2636,6 +2621,11 @@ domhandler@^5.0.2, domhandler@^5.0.3: dependencies: domelementtype "^2.3.0" +domino@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/domino/-/domino-2.1.6.tgz#fe4ace4310526e5e7b9d12c7de01b7f485a57ffe" + integrity sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ== + domutils@^3.0.1: version "3.1.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" @@ -3589,21 +3579,6 @@ grammy@^1.16.2: debug "^4.3.4" node-fetch "^2.6.9" -groq-sdk@^0.3.0: - version "0.3.2" - resolved "https://registry.yarnpkg.com/groq-sdk/-/groq-sdk-0.3.2.tgz#f5e64732791e25910a8f11d228f232816ef6047f" - integrity sha512-Xp1xOea7nqUcTMndpiA8VkjZ05jM/eUUeCILxhRF+c2etBz/myQwRcUrr5lpWc0euIt96AiBMa9aYa0Iqrh13g== - dependencies: - "@types/node" "^18.11.18" - "@types/node-fetch" "^2.6.4" - abort-controller "^3.0.0" - agentkeepalive "^4.2.1" - digest-fetch "^1.3.0" - form-data-encoder "1.7.2" - formdata-node "^4.3.2" - node-fetch "^2.6.7" - web-streams-polyfill "^3.2.1" - gtoken@^6.1.0: version "6.1.2" resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-6.1.2.tgz#aeb7bdb019ff4c3ba3ac100bbe7b6e74dce0e8bc" @@ -6646,6 +6621,13 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" +turndown@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/turndown/-/turndown-7.1.3.tgz#2890eb76c603e66bf0c9e91526582b563065c57d" + integrity sha512-Z3/iJ6IWh8VBiACWQJaA5ulPQE5E1QwvBHj00uGzdQxdRnd8fh1DPqNOJqzQDu6DkOstORrtXzf/9adB+vMtEA== + dependencies: + domino "^2.1.6" + type-fest@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.12.0.tgz#f57a27ab81c68d136a51fd71467eff94157fa1ee"