Skip to content

Commit

Permalink
feat(core): QAChain
Browse files Browse the repository at this point in the history
  • Loading branch information
LarchLiu committed Jun 25, 2023
1 parent 8b75dca commit 78d0f6f
Show file tree
Hide file tree
Showing 19 changed files with 224 additions and 60 deletions.
3 changes: 3 additions & 0 deletions packages/core/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 10 additions & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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": {
Expand Down
1 change: 1 addition & 0 deletions packages/core/scripts/create-entrypoints.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
49 changes: 49 additions & 0 deletions packages/core/src/chain/qa.ts
Original file line number Diff line number Diff line change
@@ -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
}
}
5 changes: 5 additions & 0 deletions packages/core/src/llm/openai/index.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -24,7 +25,11 @@ export class Openai extends CLLM<OpenaiConfig> {
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',
Expand Down
27 changes: 14 additions & 13 deletions packages/core/src/storage/supabase/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -16,7 +16,11 @@ export interface SupabaseImageConfig {
export class SupabaseImageStorage extends ImageStorage<SupabaseImageConfig, WebCardData> {
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}`
}

Expand Down Expand Up @@ -96,10 +100,14 @@ export interface SupabaseVectorConfig extends VectorConfig {
anonKey: string
url: string
}
export class SupabaseVectorStorage extends VectorStorage<SupabaseVectorConfig, Document<SavedVector>[]> {
export class SupabaseVectorStorage extends VectorStorage<SupabaseVectorConfig> {
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
Expand All @@ -125,22 +133,15 @@ export class SupabaseVectorStorage extends VectorStorage<SupabaseVectorConfig, D
await store.addDocuments(docs)
}

async query(question: string) {
async getRetriever() {
const vectorStore = await SupabaseVectorStore.fromExistingIndex(
this.config.embeddingsInfo.embeddings,
{
client: this.client,
tableName: this.config.embeddingsInfo.indexName,
queryName: this.config.embeddingsInfo.queryName,
})

const result = await vectorStore.similaritySearch(question, 2, {
appName: this.config.metaData.appName,
botId: this.config.metaData.botId,
userId: this.config.metaData.userId,
})

return result as Document<SavedVector>[]
return vectorStore.asRetriever()
}

getConfig(): SupabaseVectorConfig {
Expand Down
22 changes: 6 additions & 16 deletions packages/core/src/storage/types.ts
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -66,27 +66,17 @@ export abstract class ImageStorage<T, R extends SavedImage> 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<void>
query(question: string): Promise<Document<SavedVector>[]>
getRetriever(): Promise<BaseRetriever>
getType(): StorageType
getConfig(): any
getConfig(): VectorConfig
}
export interface VectorConfig {
embeddingsInfo: EmbeddingsInfo
metaData: VectorMetaData
}
export abstract class VectorStorage<T extends VectorConfig, R extends Document<SavedVector>[]> implements IVectorStorage {
export abstract class VectorStorage<T extends VectorConfig> implements IVectorStorage {
constructor(config: T, data?: WebInfoData) {
this.config = config
this.data = data
Expand All @@ -96,7 +86,7 @@ export abstract class VectorStorage<T extends VectorConfig, R extends Document<S
protected data?: WebInfoData

abstract save(data?: WebInfoData): Promise<void>
abstract query(question: string): Promise<R>
abstract getRetriever(): Promise<BaseRetriever>
abstract getType(): StorageType
abstract getConfig(): T
}
18 changes: 18 additions & 0 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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<VectorMetaData>[]
}
export interface SavedVector {
metadata: VectorMetaData
pageContent: string
}
export interface VectorMetaData {
source?: string
appName: string
botId: string
userId: string
}
1 change: 1 addition & 0 deletions packages/core/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
37 changes: 20 additions & 17 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions server/nuxt3/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Loading

1 comment on commit 78d0f6f

@vercel
Copy link

@vercel vercel bot commented on 78d0f6f Jun 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

star-nexus – ./

star-nexus.vercel.app
star-nexus-git-main-larchliu.vercel.app
star-nexus-larchliu.vercel.app

Please sign in to comment.