diff --git a/packages/core/.gitignore b/packages/core/.gitignore index 2fea744..b31a177 100644 --- a/packages/core/.gitignore +++ b/packages/core/.gitignore @@ -4,6 +4,9 @@ chain.d.ts chain/saveWebInfo.cjs chain/saveWebInfo.js chain/saveWebInfo.d.ts +chain/qa.cjs +chain/qa.js +chain/qa.d.ts llm.cjs llm.js llm.d.ts diff --git a/packages/core/package.json b/packages/core/package.json index a73fc25..00f20e1 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -29,6 +29,11 @@ "require": "./chain/saveWebInfo.cjs", "import": "./chain/saveWebInfo.js" }, + "./chain/qa": { + "types": "./chain/qa.d.ts", + "require": "./chain/qa.cjs", + "import": "./chain/qa.js" + }, "./llm": { "types": "./llm.d.ts", "require": "./llm.cjs", @@ -82,6 +87,9 @@ "chain/saveWebInfo.cjs", "chain/saveWebInfo.js", "chain/saveWebInfo.d.ts", + "chain/qa.cjs", + "chain/qa.js", + "chain/qa.d.ts", "llm.cjs", "llm.js", "llm.d.ts", @@ -123,9 +131,9 @@ "test": "vitest" }, "peerDependencies": { - "@supabase/supabase-js": "^2.22.0", + "@supabase/supabase-js": "^2.26.0", "langchain": "^0.0.96", - "ofetch": "^1.0.1" + "ofetch": "^1.1.1" }, "peerDependenciesMeta": { "@supabase/supabase-js": { diff --git a/packages/core/scripts/create-entrypoints.js b/packages/core/scripts/create-entrypoints.js index 5834eed..52cd69e 100644 --- a/packages/core/scripts/create-entrypoints.js +++ b/packages/core/scripts/create-entrypoints.js @@ -11,6 +11,7 @@ import * as path from 'node:path' export const entrypoints = { 'chain': 'chain/index', 'chain/saveWebInfo': 'chain/saveWebInfo', + 'chain/qa': 'chain/qa', 'llm': 'llm/index', 'llm/openai': 'llm/openai/index', 'storage': 'storage/index', diff --git a/packages/core/src/chain/qa.ts b/packages/core/src/chain/qa.ts new file mode 100644 index 0000000..f03290c --- /dev/null +++ b/packages/core/src/chain/qa.ts @@ -0,0 +1,49 @@ +import { RetrievalQAChain } from 'langchain/chains' +import { PromptTemplate } from 'langchain/prompts' +import type { IVectorStorage } from '../storage' +import type { PromptsLanguage, QARes } from '../types' +import { ANSWER_IN_LANGUAGE } from '../const' +import { getPromptsByTemplate } from '../utils' + +const prompt_template = `Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer. + +{context} + +Question: {question} +Answer in {language}:` + +export class QAChain { + constructor(fields: { + vectorStorage: IVectorStorage + }) { + this.vectorStorage = fields.vectorStorage + } + + private vectorStorage + + async call(question: string, language: PromptsLanguage = 'zh-CN') { + const retriever = await this.vectorStorage.getRetriever() + const config = this.vectorStorage.getConfig() + + const kv = { + language: ANSWER_IN_LANGUAGE[language], + } + const template = getPromptsByTemplate(prompt_template, kv) + + const chain = RetrievalQAChain.fromLLM( + config.embeddingsInfo.llmModel, + retriever, + { + returnSourceDocuments: true, + prompt: new PromptTemplate({ + template, + inputVariables: ['context', 'question'], + }), + }, + ) + + const res = await chain.call({ query: question }) + + return res as QARes + } +} diff --git a/packages/core/src/llm/openai/index.ts b/packages/core/src/llm/openai/index.ts index dfce52c..9cd2d7a 100644 --- a/packages/core/src/llm/openai/index.ts +++ b/packages/core/src/llm/openai/index.ts @@ -1,5 +1,6 @@ import { $fetch } from 'ofetch' import { OpenAIEmbeddings } from 'langchain/embeddings/openai' +import { ChatOpenAI } from 'langchain/chat_models/openai' import type { PromptsLanguage, SummarizeData, WebInfoData } from '../../types' import { countWord, getPromptsByTemplate, preprocessText } from '../../utils' import { ANSWER_IN_LANGUAGE, OPENAI_CHAT_API, SUMMARIZE_PROMPTS, USER_PROMPTS } from '../../const' @@ -24,7 +25,11 @@ export class Openai extends CLLM { const embeddings = new OpenAIEmbeddings({ openAIApiKey: this.config.apiKey }, { basePath: `${this.config.apiHost}/v1`, }) + const model = new ChatOpenAI({ openAIApiKey: this.config.apiKey, modelName: 'gpt-3.5-turbo', temperature: 0.2 }, { + basePath: `${this.config.apiHost}/v1`, + }) return { + llmModel: model, embeddings, indexName: 'openai_documents', queryName: 'openai_match_documents', diff --git a/packages/core/src/storage/supabase/index.ts b/packages/core/src/storage/supabase/index.ts index 0f3d338..5c80368 100644 --- a/packages/core/src/storage/supabase/index.ts +++ b/packages/core/src/storage/supabase/index.ts @@ -5,7 +5,7 @@ import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter' import { $fetch } from 'ofetch' import type { WebCardData, WebInfoData } from '../../types' import { ImageStorage, VectorStorage } from '../types' -import type { SavedVector, StorageImage, StorageType, VectorConfig } from '../types' +import type { StorageImage, StorageType, VectorConfig } from '../types' export interface SupabaseImageConfig { anonKey: string @@ -16,7 +16,11 @@ export interface SupabaseImageConfig { export class SupabaseImageStorage extends ImageStorage { constructor(config: SupabaseImageConfig, data?: StorageImage) { super(config, data) - this.client = createClient(this.config.url, this.config.anonKey) + this.client = createClient(this.config.url, this.config.anonKey, { + auth: { + persistSession: false, + }, + }) this.storageUrl = `${this.config.url}/storage/v1/object/public/${this.config.bucket}` } @@ -96,10 +100,14 @@ export interface SupabaseVectorConfig extends VectorConfig { anonKey: string url: string } -export class SupabaseVectorStorage extends VectorStorage[]> { +export class SupabaseVectorStorage extends VectorStorage { constructor(config: SupabaseVectorConfig, data?: WebInfoData) { super(config, data) - this.client = createClient(this.config.url, this.config.anonKey) + this.client = createClient(this.config.url, this.config.anonKey, { + auth: { + persistSession: false, + }, + }) } private client @@ -125,7 +133,7 @@ export class SupabaseVectorStorage extends VectorStorage[] + return vectorStore.asRetriever() } getConfig(): SupabaseVectorConfig { diff --git a/packages/core/src/storage/types.ts b/packages/core/src/storage/types.ts index 5dae00a..b42c27c 100644 --- a/packages/core/src/storage/types.ts +++ b/packages/core/src/storage/types.ts @@ -1,5 +1,5 @@ -import type { Document } from 'langchain/document' -import type { EmbeddingsInfo, SummarizeData, WebInfoData } from '../types' +import type { BaseRetriever } from 'langchain/schema' +import type { EmbeddingsInfo, SummarizeData, VectorMetaData, WebInfoData } from '../types' export type TStorage = 'DataStorage' | 'ImageStorage' | 'VectorStorage' export interface StorageType { @@ -66,27 +66,17 @@ export abstract class ImageStorage implements IImageSto abstract getConfig(): T } -export interface SavedVector { - metadata: VectorMetaData - pageContent: string -} -export interface VectorMetaData { - url: string - appName: string - botId: string - userId: string -} export interface IVectorStorage { save(data?: WebInfoData): Promise - query(question: string): Promise[]> + getRetriever(): Promise getType(): StorageType - getConfig(): any + getConfig(): VectorConfig } export interface VectorConfig { embeddingsInfo: EmbeddingsInfo metaData: VectorMetaData } -export abstract class VectorStorage[]> implements IVectorStorage { +export abstract class VectorStorage implements IVectorStorage { constructor(config: T, data?: WebInfoData) { this.config = config this.data = data @@ -96,7 +86,7 @@ export abstract class VectorStorage - abstract query(question: string): Promise + abstract getRetriever(): Promise abstract getType(): StorageType abstract getConfig(): T } diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 6ab283a..d83b8f6 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -1,4 +1,6 @@ import type { Embeddings } from 'langchain/embeddings/base' +import type { BaseLanguageModel } from 'langchain/base_language' +import type { Document } from 'langchain/document' export interface WebInfoData { title: string @@ -105,7 +107,23 @@ export interface Routes { } export interface EmbeddingsInfo { + llmModel: BaseLanguageModel embeddings: Embeddings indexName: string queryName?: string } + +export interface QARes { + text: string + sourceDocuments?: Document[] +} +export interface SavedVector { + metadata: VectorMetaData + pageContent: string +} +export interface VectorMetaData { + source?: string + appName: string + botId: string + userId: string +} diff --git a/packages/core/vite.config.ts b/packages/core/vite.config.ts index 53b75af..42ea925 100644 --- a/packages/core/vite.config.ts +++ b/packages/core/vite.config.ts @@ -5,6 +5,7 @@ import vue from '@vitejs/plugin-vue' export const entrypoints = { 'chain': 'chain/index', 'chain/saveWebInfo': 'chain/saveWebInfo', + 'chain/qa': 'chain/qa', 'llm': 'llm/index', 'llm/openai': 'llm/openai/index', 'storage': 'storage/index', diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ad8e420..ac7cdf3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -124,11 +124,11 @@ importers: packages/core: dependencies: '@supabase/supabase-js': - specifier: ^2.22.0 - version: 2.22.0 + specifier: ^2.26.0 + version: 2.26.0 langchain: specifier: ^0.0.96 - version: 0.0.96(@supabase/supabase-js@2.22.0) + version: 0.0.96(@supabase/supabase-js@2.26.0) devDependencies: ofetch: specifier: ^1.1.1 @@ -174,6 +174,9 @@ importers: '@stargram/web-hub': specifier: workspace:* version: link:../../packages/webHub + '@supabase/supabase-js': + specifier: ^2.26.0 + version: 2.26.0 '@vercel/kv': specifier: ^0.2.2 version: 0.2.2 @@ -191,7 +194,7 @@ importers: version: 1.1.1(@vue-flow/core@1.20.2) langchain: specifier: ^0.0.96 - version: 0.0.96(@supabase/supabase-js@2.22.0) + version: 0.0.96(@supabase/supabase-js@2.26.0) satori: specifier: ^0.10.1 version: 0.10.1 @@ -4781,24 +4784,24 @@ packages: - encoding dev: false - /@supabase/gotrue-js@2.27.0: - resolution: {integrity: sha512-KWoo6giZDLuF2wcN+g8DZPnTa6n9k3v7WNWTUpniPjE8H3MPMJcHka+8uHQFpvMFGUNt+ULNNbhGiaVR4PzJyA==} + /@supabase/gotrue-js@2.31.0: + resolution: {integrity: sha512-YcwlbbNfedlue/HVIXtYBb4fuOrs29gNOTl6AmyxPp4zryRxzFvslVN9kmLDBRUAVU9fnPJh2bgOR3chRjJX5w==} dependencies: cross-fetch: 3.1.6 transitivePeerDependencies: - encoding dev: false - /@supabase/postgrest-js@1.6.1: - resolution: {integrity: sha512-WDBUPOCOwcZonaCwEodwdA8hwWYOiXroDF9vWGxZxKAnuSVE2Ieci/kvhR4EsWvgGST2h90LRowgO+msXe8+fA==} + /@supabase/postgrest-js@1.7.1: + resolution: {integrity: sha512-xPRYLaZrkLbXNlzmHW6Wtf9hmcBLjjI5xUz2zj8oE2hgXGaYoZBBkpN9bmW9i17Z1f6Ujxa942AqK439XOA36A==} dependencies: cross-fetch: 3.1.6 transitivePeerDependencies: - encoding dev: false - /@supabase/realtime-js@2.7.2: - resolution: {integrity: sha512-Fi6xAl5PUkqnjl3wo4rdcQIbMG3+yTRX1aUZe/yfvTG84RMvmCXJ1yN6MmafVLeZpU1xkaz5Vx4L0tnHcLiy6w==} + /@supabase/realtime-js@2.7.3: + resolution: {integrity: sha512-c7TzL81sx2kqyxsxcDduJcHL9KJdCOoKimGP6lQSqiZKX42ATlBZpWbyy9KFGFBjAP4nyopMf5JhPi2ZH9jyNw==} dependencies: '@types/phoenix': 1.5.6 '@types/websocket': 1.0.5 @@ -4815,13 +4818,13 @@ packages: - encoding dev: false - /@supabase/supabase-js@2.22.0: - resolution: {integrity: sha512-omkgSWL1HwnpXZZy+yshFLx/qqxwk9kx9jbRM6IHNEylKrH/sz6JX7rGyIOmN9niDxMRjsCu1nwuBhD6IiF2xg==} + /@supabase/supabase-js@2.26.0: + resolution: {integrity: sha512-RXmTPTobaYAwkSobadHZmEVLmzX3SGrtRZIGfLWnLv92VzBRrjuXn0a+bJqKl50GUzsyqPA+j5pod7EwMkcH5A==} dependencies: '@supabase/functions-js': 2.1.1 - '@supabase/gotrue-js': 2.27.0 - '@supabase/postgrest-js': 1.6.1 - '@supabase/realtime-js': 2.7.2 + '@supabase/gotrue-js': 2.31.0 + '@supabase/postgrest-js': 1.7.1 + '@supabase/realtime-js': 2.7.3 '@supabase/storage-js': 2.5.1 cross-fetch: 3.1.6 transitivePeerDependencies: @@ -13233,7 +13236,7 @@ packages: resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} dev: true - /langchain@0.0.96(@supabase/supabase-js@2.22.0): + /langchain@0.0.96(@supabase/supabase-js@2.26.0): resolution: {integrity: sha512-m1d0IWjwZK+D19uBfgmfp5sUTxJXcjJb/YuIyn2cGNmXGqOH2r2cl0TUnhuFKxTXpMTXgTywd7MYF5U5/qkNTQ==} engines: {node: '>=18'} peerDependencies: @@ -13384,7 +13387,7 @@ packages: optional: true dependencies: '@anthropic-ai/sdk': 0.4.4 - '@supabase/supabase-js': 2.22.0 + '@supabase/supabase-js': 2.26.0 ansi-styles: 5.2.0 binary-extensions: 2.2.0 camelcase: 6.3.0 diff --git a/server/nuxt3/package.json b/server/nuxt3/package.json index 44a5421..1304f06 100644 --- a/server/nuxt3/package.json +++ b/server/nuxt3/package.json @@ -22,6 +22,7 @@ "dependencies": { "@stargram/core": "workspace:*", "@stargram/web-hub": "workspace:*", + "@supabase/supabase-js": "^2.26.0", "@vercel/kv": "^0.2.2", "@vue-flow/background": "^1.2.0", "@vue-flow/controls": "^1.1.0", diff --git a/server/nuxt3/server/api/save-web-info.ts b/server/nuxt3/server/api/save-web-info.ts index 1dad6ac..050cfc1 100644 --- a/server/nuxt3/server/api/save-web-info.ts +++ b/server/nuxt3/server/api/save-web-info.ts @@ -1,10 +1,9 @@ import { errorMessage } from '@stargram/core/utils' -import type { EmbeddingsInfo } from '@stargram/core' +import type { EmbeddingsInfo, VectorMetaData } from '@stargram/core' import { routes } from '@stargram/web-hub' import { SaveWebInfoChain } from '@stargram/core/chain/saveWebInfo' import { storageInfo } from '@stargram/core/storage' import type { TLLM } from '@stargram/core/llm' -import type { VectorMetaData } from '@stargram/core/storage' import { llmInfo } from '@stargram/core/llm' import { WebInfoFunction } from '@stargram/core/webInfo' import { WebCardFunction } from '@stargram/core/webCard' @@ -38,7 +37,7 @@ export default eventHandler(async (event) => { const embeddingsInfo: EmbeddingsInfo = llm.embeddingsInfo() const metaData: VectorMetaData = { - url, + source: url, appName, botId, userId, diff --git a/server/nuxt3/server/utils/index.ts b/server/nuxt3/server/utils/index.ts index 9a8d644..7a38818 100644 --- a/server/nuxt3/server/utils/index.ts +++ b/server/nuxt3/server/utils/index.ts @@ -1,4 +1,11 @@ +import { errorMessage } from '@stargram/core/utils' +import type { EmbeddingsInfo, VectorMetaData } from '@stargram/core' +import { QAChain } from '@stargram/core/chain/qa' +import { storageInfo } from '@stargram/core/storage' +import type { TLLM } from '@stargram/core/llm' +import { llmInfo } from '@stargram/core/llm' import type { AppName, OutUserConfig, ServerConfig } from '../../composables/config' +import type { Context } from './tgBot/context' import { cryption } from '~/constants' const kv = useStorage('kv') @@ -96,3 +103,51 @@ export async function getUserConfig(app: AppName, appId: string, userId: string) return false } } + +export async function MakeQAChain(question: string, context: Context, appName: string, botId: string, userId: string) { + const config = context.USER_CONFIG as UserConfig + + const llm = new (llmInfo[config.llm.select as TLLM])(config.llm.config) + + const embeddingsInfo: EmbeddingsInfo = llm.embeddingsInfo() + const metaData: VectorMetaData = { + appName, + botId, + userId, + } + const vectorStorage = new (storageInfo.VectorStorage[config.vectorStorage.select])({ ...config.vectorStorage.config, embeddingsInfo, metaData }) + + const chain = new QAChain({ + vectorStorage, + }) + + const info = await chain.call(question, config.llm.config.lang).catch(e => errorMessage(e)) + + let message = 'Answer: ' + let meta = 'Source: ' + if (typeof info === 'string') { + message = `Error Info: ${info}\n` + } + else { + message += info.text + if (info.sourceDocuments) { + const uniqueUrls = new Set(info.sourceDocuments.map((d) => { + return d.metadata.source + })) + const uniqueMatchs = [...uniqueUrls] + meta += uniqueMatchs.join('\n') || '' + message += `\n${meta}` + } + } + + try { + if (appName === 'telegram') + return (await sendMessageToTelegramWithContext(context)(message)) + else if (appName === 'slack') + return (await sendMessageToSlackBot(config.app.config.webhook, message)) + } + catch (error) { + console.error(error) + return new Response(errorToString(error), { status: 200 }) + } +} diff --git a/server/nuxt3/server/utils/tgBot/command.ts b/server/nuxt3/server/utils/tgBot/command.ts index d0aef0b..3ef4554 100644 --- a/server/nuxt3/server/utils/tgBot/command.ts +++ b/server/nuxt3/server/utils/tgBot/command.ts @@ -4,10 +4,11 @@ import { import type { Context } from '../../utils/tgBot/context' import { CONST, ENV, I18N } from '../../utils/tgBot/env' import type { OutUserConfig, ServerConfig } from '../../../composables/config' +import { TelegramQAChain } from './makeChain' import { cryption } from '~/constants' type ScopeType = 'all_private_chats' | 'all_group_chats' | 'all_chat_administrators' -type CommandType = '/start' | '/config' +type CommandType = '/start' | '/config' | '/qa' interface CommandOpt { scopes: ScopeType[] fn: (message: any, command: any, subcommand: any, context: any) => Promise @@ -57,6 +58,11 @@ const commandHandlers: CommandHandlers = { fn: commandSystem, needAuth: commandAuthCheck.default, }, + '/qa': { + scopes: ['all_private_chats', 'all_chat_administrators'], + fn: commandQA, + needAuth: commandAuthCheck.default, + }, } async function commandCreateNewChatContext(message: any, command: string, subcommand: string, context: Context) { @@ -69,7 +75,7 @@ async function commandCreateNewChatContext(message: any, command: string, subcom userId: context.CURRENT_CHAT_CONTEXT.chat_id, } const encode = cryption.encode(JSON.stringify(info)) - return sendMessageToTelegramWithContext(context)(`User ID: ${context.CURRENT_CHAT_CONTEXT.chat_id}\nGo to this link to set your config: ${domain}/user-config?code=${encode}`) + return sendMessageToTelegramWithContext(context)(`User ID: ${context.CURRENT_CHAT_CONTEXT.chat_id}\nSet Config: [Go to this link](${domain}/user-config?code=${encode})`) } } catch (e: any) { @@ -78,7 +84,7 @@ async function commandCreateNewChatContext(message: any, command: string, subcom } async function commandSystem(message: any, command: string, subcommand: string, context: Context) { - let msg = 'Current User Config:\n' + let msg = 'Current User Config:\n\n' const userConfig = await getUserConfig('telegram', context.SHARE_CONTEXT.currentBotId, context.CURRENT_CHAT_CONTEXT.chat_id) const myConfig: any = {} if (userConfig) { @@ -90,13 +96,28 @@ async function commandSystem(message: any, command: string, subcommand: string, .forEach(key => myConfig[key] = userConfig[key as keyof ServerConfig]) } const showConfig = JSON.stringify(myConfig, null, 2) - msg += '
'
-  msg += `${showConfig}`
-  msg += '
' - context.CURRENT_CHAT_CONTEXT.parse_mode = 'HTML' + msg += '```\n' + msg += `${showConfig}\n` + msg += '```' return sendMessageToTelegramWithContext(context)(msg) } +async function commandQA(message: any, command: string, subcommand: string, context: Context) { + const question = subcommand + if (!question) { + return sendMessageToTelegramWithContext(context)('Please enter your question with command. The format is: /qa ') + } + else { + try { + const msg = await TelegramQAChain(question, context) + return sendMessageToTelegramWithContext(context)(msg) + } + catch (e: any) { + return sendMessageToTelegramWithContext(context)(`ERROR: ${e.message}`) + } + } +} + export async function handleCommandMessage(message: any, context: Context) { for (const key in commandHandlers) { if (message.text === key || message.text.startsWith(`${key} `)) { diff --git a/server/nuxt3/server/utils/tgBot/i18n/en.ts b/server/nuxt3/server/utils/tgBot/i18n/en.ts index 3addfbd..3093f46 100644 --- a/server/nuxt3/server/utils/tgBot/i18n/en.ts +++ b/server/nuxt3/server/utils/tgBot/i18n/en.ts @@ -17,6 +17,7 @@ export default { summary: 'The following commands are currently supported:\n', start: 'Get your ID and settings url', config: 'Preview user config', + qa: 'Ask your question', }, }, } diff --git a/server/nuxt3/server/utils/tgBot/i18n/zh-hans.ts b/server/nuxt3/server/utils/tgBot/i18n/zh-hans.ts index a0af593..38be55a 100644 --- a/server/nuxt3/server/utils/tgBot/i18n/zh-hans.ts +++ b/server/nuxt3/server/utils/tgBot/i18n/zh-hans.ts @@ -20,6 +20,7 @@ export default { summary: '当前支持以下命令:\n', start: '获取你的ID和用户设置网址', config: '查看用户设置', + qa: '提问', }, }, } diff --git a/server/nuxt3/server/utils/tgBot/i18n/zh-hant.ts b/server/nuxt3/server/utils/tgBot/i18n/zh-hant.ts index a913f3f..c42aafc 100644 --- a/server/nuxt3/server/utils/tgBot/i18n/zh-hant.ts +++ b/server/nuxt3/server/utils/tgBot/i18n/zh-hant.ts @@ -20,6 +20,7 @@ export default { summary: '當前支持的命令如下:\n', start: '獲取您的ID和设置网址', config: '查看用户设置', + qa: '提问', }, }, } diff --git a/server/nuxt3/server/utils/tgBot/makeChain.ts b/server/nuxt3/server/utils/tgBot/makeChain.ts index 2dcedef..0d9f5f7 100644 --- a/server/nuxt3/server/utils/tgBot/makeChain.ts +++ b/server/nuxt3/server/utils/tgBot/makeChain.ts @@ -1,9 +1,10 @@ import { errorMessage } from '@stargram/core/utils' import type { Context } from './context' -export async function TelegramSaveWebInfoChain(stargramHub: string, text: string, context: Context) { +export async function TelegramSaveWebInfoChain(text: string, context: Context) { const regex = /(http(s)?:\/\/)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:[0-9]{1,5})?[-a-zA-Z0-9()@:%_\\\+\.~#?&//=]*/g const matchs = text.match(regex) + const stargramHub = context.SHARE_CONTEXT.currentHost // const infoArr = [] if (matchs) { let i = 0 @@ -75,3 +76,8 @@ export async function TelegramSaveWebInfoChain(stargramHub: string, text: string throw new Error('No Supported Website.') } } + +export async function TelegramQAChain(question: string, context: Context) { + MakeQAChain(question, context, 'telegram', context.SHARE_CONTEXT.currentBotId, context.SHARE_CONTEXT.chatId) + return `Question: ${question}` +} diff --git a/server/nuxt3/server/utils/tgBot/message.ts b/server/nuxt3/server/utils/tgBot/message.ts index 3acf83b..161f1f1 100644 --- a/server/nuxt3/server/utils/tgBot/message.ts +++ b/server/nuxt3/server/utils/tgBot/message.ts @@ -150,7 +150,7 @@ async function msgProcessByStarNuxts(message: any, context: Context) { try { // console.log(`Ask:${message.text}` || '') setTimeout(() => sendChatActionToTelegramWithContext(context)('typing').catch(console.error), 0) - const res = await TelegramSaveWebInfoChain(context.SHARE_CONTEXT.currentHost, message.text, context) + const res = await TelegramSaveWebInfoChain(message.text, context) return sendMessageToTelegramWithContext(context)(res) } catch (e) {