mirror of
https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
synced 2025-11-13 04:33:42 +08:00
feat: #77
This commit is contained in:
@@ -7,6 +7,8 @@ import { RunnableSequence } from "@langchain/core/runnables";
|
||||
import { StringOutputParser } from "@langchain/core/output_parsers";
|
||||
import { Pinecone } from "@pinecone-database/pinecone";
|
||||
import { PineconeStore } from "@langchain/pinecone";
|
||||
import { getServerSideConfig } from "@/app/config/server";
|
||||
import { QdrantVectorStore } from "@langchain/community/vectorstores/qdrant";
|
||||
|
||||
export class RAGSearch extends Tool {
|
||||
static lc_name() {
|
||||
@@ -34,21 +36,32 @@ export class RAGSearch extends Tool {
|
||||
|
||||
/** @ignore */
|
||||
async _call(inputs: string, runManager?: CallbackManagerForToolRun) {
|
||||
const pinecone = new Pinecone();
|
||||
const pineconeIndex = pinecone.Index(process.env.PINECONE_INDEX!);
|
||||
const vectorStore = await PineconeStore.fromExistingIndex(this.embeddings, {
|
||||
pineconeIndex,
|
||||
});
|
||||
const serverConfig = getServerSideConfig();
|
||||
// const pinecone = new Pinecone();
|
||||
// const pineconeIndex = pinecone.Index(serverConfig.pineconeIndex!);
|
||||
// const vectorStore = await PineconeStore.fromExistingIndex(this.embeddings, {
|
||||
// pineconeIndex,
|
||||
// });
|
||||
const vectorStore = await QdrantVectorStore.fromExistingCollection(
|
||||
this.embeddings,
|
||||
{
|
||||
url: process.env.QDRANT_URL,
|
||||
apiKey: process.env.QDRANT_API_KEY,
|
||||
collectionName: this.sessionId,
|
||||
},
|
||||
);
|
||||
|
||||
let context;
|
||||
const returnCunt = process.env.RAG_RETURN_COUNT
|
||||
? parseInt(process.env.RAG_RETURN_COUNT, 10)
|
||||
const returnCunt = serverConfig.ragReturnCount
|
||||
? parseInt(serverConfig.ragReturnCount, 10)
|
||||
: 4;
|
||||
const results = await vectorStore.similaritySearch(inputs, returnCunt, {
|
||||
sessionId: this.sessionId,
|
||||
});
|
||||
console.log("[rag-search]", { inputs, returnCunt });
|
||||
// const results = await vectorStore.similaritySearch(inputs, returnCunt, {
|
||||
// sessionId: this.sessionId,
|
||||
// });
|
||||
const results = await vectorStore.similaritySearch(inputs, returnCunt);
|
||||
context = formatDocumentsAsString(results);
|
||||
console.log("[rag-search]", context);
|
||||
console.log("[rag-search]", { context });
|
||||
return context;
|
||||
// const input = `Text:${context}\n\nQuestion:${inputs}\n\nI need you to answer the question based on the text.`;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { ACCESS_CODE_PREFIX, ModelProvider } from "@/app/constant";
|
||||
import { OpenAIEmbeddings } from "@langchain/openai";
|
||||
import { Pinecone } from "@pinecone-database/pinecone";
|
||||
import { PineconeStore } from "@langchain/pinecone";
|
||||
import { QdrantVectorStore } from "@langchain/community/vectorstores/qdrant";
|
||||
import { getServerSideConfig } from "@/app/config/server";
|
||||
|
||||
interface RequestBody {
|
||||
@@ -27,26 +28,40 @@ async function handle(req: NextRequest) {
|
||||
const reqBody: RequestBody = await req.json();
|
||||
const authToken = req.headers.get("Authorization") ?? "";
|
||||
const token = authToken.trim().replaceAll("Bearer ", "").trim();
|
||||
|
||||
const pinecone = new Pinecone();
|
||||
const pineconeIndex = pinecone.Index(process.env.PINECONE_INDEX!);
|
||||
const serverConfig = getServerSideConfig();
|
||||
// const pinecone = new Pinecone();
|
||||
// const pineconeIndex = pinecone.Index(serverConfig.pineconeIndex!);
|
||||
const apiKey = getOpenAIApiKey(token);
|
||||
const baseUrl = getOpenAIBaseUrl(reqBody.baseUrl);
|
||||
const embeddings = new OpenAIEmbeddings(
|
||||
{
|
||||
modelName: process.env.RAG_EMBEDDING_MODEL ?? "text-embedding-3-large",
|
||||
modelName: serverConfig.ragEmbeddingModel ?? "text-embedding-3-large",
|
||||
openAIApiKey: apiKey,
|
||||
},
|
||||
{ basePath: baseUrl },
|
||||
);
|
||||
const vectorStore = await PineconeStore.fromExistingIndex(embeddings, {
|
||||
pineconeIndex,
|
||||
});
|
||||
const results = await vectorStore.similaritySearch(reqBody.query, 1, {
|
||||
sessionId: reqBody.sessionId,
|
||||
});
|
||||
console.log(results);
|
||||
return NextResponse.json(results, {
|
||||
// const vectorStore = await PineconeStore.fromExistingIndex(embeddings, {
|
||||
// pineconeIndex,
|
||||
// });
|
||||
// const results = await vectorStore.similaritySearch(reqBody.query, 4, {
|
||||
// sessionId: reqBody.sessionId,
|
||||
// });
|
||||
const vectorStore = await QdrantVectorStore.fromExistingCollection(
|
||||
embeddings,
|
||||
{
|
||||
url: process.env.QDRANT_URL,
|
||||
apiKey: process.env.QDRANT_API_KEY,
|
||||
collectionName: reqBody.sessionId,
|
||||
},
|
||||
);
|
||||
const returnCunt = serverConfig.ragReturnCount
|
||||
? parseInt(serverConfig.ragReturnCount, 10)
|
||||
: 4;
|
||||
const response = await vectorStore.similaritySearch(
|
||||
reqBody.query,
|
||||
returnCunt,
|
||||
);
|
||||
return NextResponse.json(response, {
|
||||
status: 200,
|
||||
});
|
||||
} catch (e) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import { FileInfo } from "@/app/client/platforms/utils";
|
||||
import mime from "mime";
|
||||
import LocalFileStorage from "@/app/utils/local_file_storage";
|
||||
import S3FileStorage from "@/app/utils/s3_file_storage";
|
||||
import { QdrantVectorStore } from "@langchain/community/vectorstores/qdrant";
|
||||
|
||||
interface RequestBody {
|
||||
sessionId: string;
|
||||
@@ -80,16 +81,17 @@ async function handle(req: NextRequest) {
|
||||
const apiKey = getOpenAIApiKey(token);
|
||||
const baseUrl = getOpenAIBaseUrl(reqBody.baseUrl);
|
||||
const serverConfig = getServerSideConfig();
|
||||
const pinecone = new Pinecone();
|
||||
const pineconeIndex = pinecone.Index(process.env.PINECONE_INDEX!);
|
||||
// const pinecone = new Pinecone();
|
||||
// const pineconeIndex = pinecone.Index(serverConfig.pineconeIndex!);
|
||||
const embeddings = new OpenAIEmbeddings(
|
||||
{
|
||||
modelName: process.env.RAG_EMBEDDING_MODEL ?? "text-embedding-3-large",
|
||||
modelName: serverConfig.ragEmbeddingModel,
|
||||
openAIApiKey: apiKey,
|
||||
},
|
||||
{ basePath: baseUrl },
|
||||
);
|
||||
//https://js.langchain.com/docs/integrations/vectorstores/pinecone
|
||||
// https://js.langchain.com/docs/integrations/vectorstores/pinecone
|
||||
// https://js.langchain.com/docs/integrations/vectorstores/qdrant
|
||||
// process files
|
||||
for (let i = 0; i < reqBody.fileInfos.length; i++) {
|
||||
const fileInfo = reqBody.fileInfos[i];
|
||||
@@ -121,22 +123,33 @@ async function handle(req: NextRequest) {
|
||||
};
|
||||
});
|
||||
// split
|
||||
const chunkSize = process.env.RAG_CHUNK_SIZE
|
||||
? parseInt(process.env.RAG_CHUNK_SIZE, 10)
|
||||
const chunkSize = serverConfig.ragChunkSize
|
||||
? parseInt(serverConfig.ragChunkSize, 10)
|
||||
: 2000;
|
||||
const chunkOverlap = process.env.RAG_CHUNK_OVERLAP
|
||||
? parseInt(process.env.RAG_CHUNK_OVERLAP, 10)
|
||||
const chunkOverlap = serverConfig.ragChunkOverlap
|
||||
? parseInt(serverConfig.ragChunkOverlap, 10)
|
||||
: 200;
|
||||
const textSplitter = new RecursiveCharacterTextSplitter({
|
||||
chunkSize: chunkSize,
|
||||
chunkOverlap: chunkOverlap,
|
||||
});
|
||||
const splits = await textSplitter.splitDocuments(docs);
|
||||
// remove history
|
||||
await PineconeStore.fromDocuments(splits, embeddings, {
|
||||
pineconeIndex,
|
||||
maxConcurrency: 5,
|
||||
});
|
||||
const vectorStore = await QdrantVectorStore.fromDocuments(
|
||||
splits,
|
||||
embeddings,
|
||||
{
|
||||
url: process.env.QDRANT_URL,
|
||||
apiKey: process.env.QDRANT_API_KEY,
|
||||
collectionName: reqBody.sessionId,
|
||||
},
|
||||
);
|
||||
// await PineconeStore.fromDocuments(splits, embeddings, {
|
||||
// pineconeIndex,
|
||||
// maxConcurrency: 5,
|
||||
// });
|
||||
// const vectorStore = await PineconeStore.fromExistingIndex(embeddings, {
|
||||
// pineconeIndex,
|
||||
// });
|
||||
}
|
||||
return NextResponse.json(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user