Update langchainJS version to 0.0.212 (#213)

* Enhance AIState documentation

* Update langchain to 0.0.212

* Migrate from openai v3 to v4

* Add check for undefined chain in runChain

* Set embedding model too when proxy url is provided

* Fix import for migration

* Fix bug updating vectordb after clearing

* Add more detail in logging

* Update styling for openai proxy url setting

* 2.4.5
This commit is contained in:
Logan Yang 2023-12-29 15:47:29 -08:00 committed by GitHub
parent a367d374eb
commit 773a379cc1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 1100 additions and 407 deletions

View file

@ -1,7 +1,7 @@
{
"id": "copilot",
"name": "Copilot",
"version": "2.4.4",
"version": "2.4.5",
"minAppVersion": "0.15.0",
"description": "A ChatGPT Copilot in Obsidian.",
"author": "Logan Yang",

1391
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "obsidian-copilot",
"version": "2.4.4",
"version": "2.4.5",
"description": "ChatGPT integration for Obsidian",
"main": "main.js",
"scripts": {
@ -47,7 +47,7 @@
"eventsource-parser": "^1.0.0",
"koa": "^2.14.2",
"koa-proxies": "^0.12.3",
"langchain": "^0.0.103",
"langchain": "^0.0.212",
"next-i18next": "^13.2.2",
"pouchdb": "^8.0.1",
"prop-types": "^15.8.1",

View file

@ -95,6 +95,41 @@ export interface SetChainOptions {
forceNewCreation?: boolean;
}
/**
* AIState manages the chat model, LangChain, and related state.
*
* initMemory() - Initializes the memory buffer for the chat history.
*
* initChatPrompt() - Initializes the chat prompt template with placeholders for chat history and user input.
*
* validateChainType() - Throws error if chain type is invalid.
*
* validateChatModel() - Throws error if chat model is not initialized.
*
* getModelConfig() - Gets model configuration based on vendor.
*
* buildModelMap() - Builds map of available models and required info to instantiate them.
*
* getEmbeddingsAPI() - Gets the appropriate embeddings API instance based on settings.
*
* clearChatMemory() - Clears the chat history memory.
*
* setChatModel() - Creates and sets the chat model instance based on name.
*
* setModel() - Sets new model name and display name, creates new chain.
*
* createChain() - Creates new chain or updates existing with new model.
*
* setChain() - Validates and sets the chain instance of specified type.
*
* buildIndex() - Builds vector index for note content using embeddings API.
*
* countTokens() - Counts number of tokens for given input string.
*
* runChatModel() - Runs chat model and handles streaming output.
*
* runChain() - Runs the LangChain and handles streaming output.
*/
class AIState {
private static chatModel: BaseChatModel;
private static chatOpenAI: ChatOpenAI;
@ -263,12 +298,22 @@ class AIState {
openAIProxyBaseUrl,
} = this.langChainParams;
const OpenAIEmbeddingsAPI = new OpenAIEmbeddings({
openAIApiKey,
maxRetries: 3,
maxConcurrency: 3,
timeout: 10000,
});
// Note that openAIProxyBaseUrl has the highest priority.
// If openAIProxyBaseUrl is set, it overrides both chat and embedding models.
const OpenAIEmbeddingsAPI = openAIProxyBaseUrl ?
new ProxyOpenAIEmbeddings({
openAIApiKey,
maxRetries: 3,
maxConcurrency: 3,
timeout: 10000,
openAIProxyBaseUrl,
}):
new OpenAIEmbeddings({
openAIApiKey,
maxRetries: 3,
maxConcurrency: 3,
timeout: 10000,
});
switch(this.langChainParams.embeddingProvider) {
case OPENAI:
@ -409,6 +454,7 @@ class AIState {
switch (chainType) {
case ChainType.LLM_CHAIN: {
// For initial load of the plugin
if (options.forceNewCreation) {
AIState.chain = ChainFactory.createNewLLMChain({
llm: AIState.chatModel,
@ -416,6 +462,7 @@ class AIState {
prompt: options.prompt || this.chatPrompt,
}) as ConversationChain;
} else {
// For navigating back to the plugin view
AIState.chain = ChainFactory.getLLMChainFromMap({
llm: AIState.chatModel,
memory: this.memory,
@ -562,7 +609,7 @@ class AIState {
debug = false,
) {
// Check if chain is initialized properly
if (!isSupportedChain(AIState.chain)) {
if (!AIState.chain || !isSupportedChain(AIState.chain)) {
console.error(
'Chain is not initialized properly, re-initializing chain: ',
this.langChainParams.chainType
@ -634,7 +681,9 @@ class AIState {
}
}
/**
* React hook to manage state related to model, chain and memory in Chat component.
*/
export function useAIState(
aiState: AIState,
): [

View file

@ -1,3 +1,4 @@
import { BaseRetriever } from "@langchain/core/retrievers";
import { BaseLanguageModel } from "langchain/base_language";
import {
BaseChain,
@ -5,7 +6,6 @@ import {
ConversationalRetrievalQAChain,
LLMChainInput
} from "langchain/chains";
import { BaseRetriever } from "langchain/schema";
export interface RetrievalChainParams {
llm: BaseLanguageModel;

View file

@ -1,7 +1,8 @@
import { ChatOpenAI } from 'langchain/chat_models/openai';
import { OpenAIEmbeddings } from "langchain/embeddings/openai";
import { Configuration, OpenAIApi } from "openai";
import OpenAI from "openai";
// Migrated to OpenAI v4 client from v3: https://github.com/openai/openai-node/discussions/217
export class ProxyChatOpenAI extends ChatOpenAI {
constructor(
fields?: any,
@ -9,16 +10,15 @@ export class ProxyChatOpenAI extends ChatOpenAI {
super(fields ?? {});
// Use LocalAIModel if it is set
// TODO: Remove this once move over to LM Studio
const modelName = fields.localAIModel ? fields.localAIModel : fields.modelName;
const clientConfig = new Configuration({
// Reinitialize the client with the updated clientConfig
this["client"] = new OpenAI({
...this["clientConfig"],
modelName,
basePath: fields.openAIProxyBaseUrl,
baseURL: fields.openAIProxyBaseUrl,
});
// Reinitialize the client with the updated clientConfig
this["client"] = new OpenAIApi(clientConfig);
}
}
@ -28,12 +28,10 @@ export class ProxyOpenAIEmbeddings extends OpenAIEmbeddings {
) {
super(fields ?? {});
const clientConfig = new Configuration({
...this["clientConfig"],
basePath: fields.openAIProxyBaseUrl,
});
// Reinitialize the client with the updated clientConfig
this["client"] = new OpenAIApi(clientConfig);
this["client"] = new OpenAI({
...this["clientConfig"],
baseURL: fields.openAIProxyBaseUrl,
});
}
}

View file

@ -381,9 +381,11 @@ export default class CopilotPlugin extends Plugin {
// Clear the vectorstore db
await this.dbVectorStores.destroy();
// Reinitialize the database
this.dbVectorStores = new PouchDB<VectorStoreDocument>('copilot_vector_stores'); //
this.dbVectorStores = new PouchDB<VectorStoreDocument>('copilot_vector_stores');
// Make sure to update the instance with VectorDBManager
VectorDBManager.updateDBInstance(this.dbVectorStores);
new Notice('Local vector store cleared successfully.');
console.log('Local vector store cleared successfully.');
console.log('Local vector store cleared successfully, new instance created.');
} catch (err) {
console.error("Error clearing the local vector store:", err);
new Notice('An error occurred while clearing the local vector store.');

View file

@ -489,10 +489,14 @@ export class CopilotSettingTab extends PluginSettingTab {
createFragment((frag) => {
frag.createEl(
'strong',
{ text: "CAUTION: This will override the default OpenAI API URL! Use with discretion!" }
{ text: "CAUTION: This overrides the OpenAI API URL " },
);
frag.createEl('br');
frag.appendText("Leave blank to use the official OpenAI API.");
frag.createEl('strong', {
text: "for both chat and embedding models when OpenAI models are picked!"
});
frag.createEl('br');
frag.appendText(" Leave blank to use the official OpenAI API.");
})
)
.addText((text) => {

View file

@ -23,6 +23,10 @@ class VectorDBManager {
this.db = db;
}
public static updateDBInstance(newDb: PouchDB.Database): void {
this.db = newDb;
}
public static getDocumentHash(sourceDocument: string): string {
return MD5(sourceDocument).toString();
}

View file

@ -25,5 +25,6 @@
"2.4.1": "0.15.0",
"2.4.2": "0.15.0",
"2.4.3": "0.15.0",
"2.4.4": "0.15.0"
"2.4.4": "0.15.0",
"2.4.5": "0.15.0"
}