@librechat/agents 1.7.2 → 1.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,27 +1,34 @@
1
1
  // src/llm/providers.ts
2
2
  import { ChatOpenAI } from '@langchain/openai';
3
+ import { ChatOllama } from '@langchain/ollama';
3
4
  import { ChatBedrockConverse } from '@langchain/aws';
4
5
  import { ChatAnthropic } from '@langchain/anthropic';
5
6
  import { ChatMistralAI } from '@langchain/mistralai';
6
7
  import { ChatVertexAI } from '@langchain/google-vertexai';
7
8
  import { BedrockChat } from '@langchain/community/chat_models/bedrock/web';
8
- import type * as t from '@/types';
9
+ import type { ChatModelConstructorMap, ProviderOptionsMap, ChatModelMap } from '@/types';
9
10
  import { Providers } from '@/common';
10
11
 
11
- export const llmProviders: Record<Providers, t.ChatModelConstructor> = {
12
+ export const llmProviders: Partial<ChatModelConstructorMap> = {
12
13
  [Providers.OPENAI]: ChatOpenAI,
14
+ [Providers.OLLAMA]: ChatOllama,
13
15
  [Providers.VERTEXAI]: ChatVertexAI,
14
- [Providers.BEDROCK_LEGACY]: BedrockChat as unknown as t.ChatModelConstructor,
16
+ [Providers.BEDROCK_LEGACY]: BedrockChat,
15
17
  [Providers.MISTRALAI]: ChatMistralAI,
16
- [Providers.BEDROCK]: ChatBedrockConverse as unknown as t.ChatModelConstructor,
18
+ [Providers.BEDROCK]: ChatBedrockConverse,
17
19
  [Providers.ANTHROPIC]: ChatAnthropic,
18
20
  };
19
21
 
20
- export const getChatModelClass = (provider: Providers): t.ChatModelConstructor => {
22
+ export const doubleCallProviders = new Set<Providers | string>([Providers.ANTHROPIC, Providers.BEDROCK]);
23
+ export const manualToolStreamProviders = new Set<Providers | string>([Providers.ANTHROPIC, Providers.BEDROCK, Providers.OLLAMA]);
24
+
25
+ export const getChatModelClass = <P extends Providers>(
26
+ provider: P
27
+ ): new (config: ProviderOptionsMap[P]) => ChatModelMap[P] => {
21
28
  const ChatModelClass = llmProviders[provider];
22
29
  if (!ChatModelClass) {
23
30
  throw new Error(`Unsupported LLM provider: ${provider}`);
24
31
  }
25
32
 
26
33
  return ChatModelClass;
27
- };
34
+ };
package/src/run.ts CHANGED
@@ -6,6 +6,7 @@ import type { RunnableConfig } from '@langchain/core/runnables';
6
6
  import type { ClientCallbacks, SystemCallbacks } from '@/graphs/Graph';
7
7
  import type * as t from '@/types';
8
8
  import { GraphEvents, Providers, Callback } from '@/common';
9
+ import { doubleCallProviders } from '@/llm/providers';
9
10
  import { createTitleRunnable } from '@/utils/title';
10
11
  import { StandardGraph } from '@/graphs/Graph';
11
12
  import { HandlerRegistry } from '@/events';
@@ -54,7 +55,7 @@ export class Run<T extends t.BaseGraphState> {
54
55
  }
55
56
 
56
57
  private createStandardGraph(config: t.StandardGraphConfig): t.CompiledWorkflow<t.IState, Partial<t.IState>, string> {
57
- const { llmConfig, instructions, additional_instructions, streamBuffer, tools = [] } = config;
58
+ const { llmConfig, instructions, additional_instructions, streamBuffer, toolEnd, tools = [] } = config;
58
59
  const { provider, ...clientOptions } = llmConfig;
59
60
 
60
61
  const standardGraph = new StandardGraph({
@@ -65,6 +66,7 @@ export class Run<T extends t.BaseGraphState> {
65
66
  clientOptions,
66
67
  additional_instructions,
67
68
  streamBuffer,
69
+ toolEnd,
68
70
  });
69
71
  this.Graph = standardGraph;
70
72
  return standardGraph.createWorkflow();
@@ -115,9 +117,8 @@ export class Run<T extends t.BaseGraphState> {
115
117
  const { data, name, metadata, ...info } = event;
116
118
 
117
119
  let eventName: t.EventName = info.event;
118
- const isDoubleCallProvider = provider === Providers.ANTHROPIC || provider === Providers.BEDROCK;
119
- if (hasTools && isDoubleCallProvider && eventName === GraphEvents.CHAT_MODEL_STREAM) {
120
- /* Skipping CHAT_MODEL_STREAM event for Anthropic due to double-call edge case */
120
+ if (hasTools && doubleCallProviders.has(provider) && eventName === GraphEvents.CHAT_MODEL_STREAM) {
121
+ /* Skipping CHAT_MODEL_STREAM event due to double-call edge case */
121
122
  continue;
122
123
  }
123
124
 
@@ -20,7 +20,7 @@ export async function getArgs(): Promise<{ userName: string; location: string; p
20
20
  alias: 'p',
21
21
  type: 'string',
22
22
  description: 'LLM provider',
23
- choices: ['openAI', 'anthropic', 'mistralai', 'vertexai', 'bedrock'],
23
+ choices: ['openAI', 'anthropic', 'mistralai', 'vertexai', 'bedrock', 'ollama'],
24
24
  default: 'openAI'
25
25
  })
26
26
  .help()
@@ -48,8 +48,8 @@ async function testStandardStreaming(): Promise<void> {
48
48
  streaming: false,
49
49
  },
50
50
  tools: [setMemory],
51
- instructions: 'You can use the `set_memory` tool to save important data about the user into memory.',
52
- toolEnd: false,
51
+ instructions: 'You can use the `set_memory` tool to save important data about the user into memory. If there is nothing to note about the user specifically, respond with `nothing`.',
52
+ toolEnd: true,
53
53
  },
54
54
  returnContent: true,
55
55
  });
@@ -65,7 +65,7 @@ async function testStandardStreaming(): Promise<void> {
65
65
 
66
66
  console.log('Test 1: Simple message test');
67
67
 
68
- const userMessage = `hi my name is ${userName}`;
68
+ const userMessage = `hi`;
69
69
 
70
70
  conversationHistory.push(new HumanMessage(userMessage));
71
71
 
@@ -1,16 +1,14 @@
1
- import { END } from '@langchain/langgraph';
1
+ import { END, MessagesAnnotation } from '@langchain/langgraph';
2
2
  import { ToolMessage, isBaseMessage } from '@langchain/core/messages';
3
3
  import type { RunnableConfig, RunnableToolLike } from '@langchain/core/runnables';
4
- import type { MessagesState } from '@langchain/langgraph/dist/graph/message';
5
4
  import type { BaseMessage, AIMessage } from '@langchain/core/messages';
6
5
  import type { StructuredToolInterface } from '@langchain/core/tools';
7
6
  import type * as t from '@/types';
8
7
  import{ RunnableCallable } from '@/utils';
9
8
  import { GraphNodeKeys } from '@/common';
10
9
 
11
- export class ToolNode<
12
- T extends BaseMessage[] | MessagesState
13
- > extends RunnableCallable<T, T> {
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
+ export class ToolNode<T = any> extends RunnableCallable<T, T> {
14
12
  tools: t.GenericTool[];
15
13
  private toolMap: Map<string, StructuredToolInterface | RunnableToolLike>;
16
14
  private loadRuntimeTools?: t.ToolRefGenerator;
@@ -31,10 +29,8 @@ export class ToolNode<
31
29
  this.loadRuntimeTools = loadRuntimeTools;
32
30
  }
33
31
 
34
- private async run(
35
- input: BaseMessage[] | MessagesState,
36
- config: RunnableConfig
37
- ): Promise<BaseMessage[] | MessagesState> {
32
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
33
+ protected async run(input: any, config: RunnableConfig): Promise<T> {
38
34
  const message = Array.isArray(input)
39
35
  ? input[input.length - 1]
40
36
  : input.messages[input.messages.length - 1];
@@ -86,13 +82,13 @@ export class ToolNode<
86
82
  }) ?? []
87
83
  );
88
84
 
89
- return Array.isArray(input) ? outputs : { messages: outputs };
85
+ return (Array.isArray(input) ? outputs : { messages: outputs }) as T;
90
86
  }
91
87
  }
92
88
 
93
89
  export function toolsCondition(
94
- state: BaseMessage[] | MessagesState
95
- ): GraphNodeKeys.TOOLS | typeof END {
90
+ state: BaseMessage[] | typeof MessagesAnnotation.State
91
+ ): 'tools' | typeof END {
96
92
  const message = Array.isArray(state)
97
93
  ? state[state.length - 1]
98
94
  : state.messages[state.messages.length - 1];
package/src/types/llm.ts CHANGED
@@ -1,38 +1,67 @@
1
1
  // src/types/llm.ts
2
2
  import { ChatOpenAI } from '@langchain/openai';
3
+ import { ChatOllama } from '@langchain/ollama';
3
4
  import { ChatAnthropic } from '@langchain/anthropic';
4
5
  import { ChatMistralAI } from '@langchain/mistralai';
5
6
  import { ChatBedrockConverse } from '@langchain/aws';
6
7
  import { ChatVertexAI } from '@langchain/google-vertexai';
7
- import { BedrockChat, BedrockChatFields } from '@langchain/community/chat_models/bedrock/web';
8
+ import { BedrockChat } from '@langchain/community/chat_models/bedrock/web';
9
+ import type { Runnable } from '@langchain/core/runnables';
10
+ import type { StructuredTool } from '@langchain/core/tools';
11
+ import type { BindToolsInput } from '@langchain/core/language_models/chat_models';
12
+ import type { BedrockChatFields } from '@langchain/community/chat_models/bedrock/web';
13
+ import type { ChatOpenAIFields } from '@langchain/openai';
14
+ import type { OpenAI as OpenAIClient } from 'openai';
8
15
  import type { ChatVertexAIInput } from '@langchain/google-vertexai';
9
16
  import type { ChatBedrockConverseInput } from '@langchain/aws';
10
17
  import type { ChatMistralAIInput } from '@langchain/mistralai';
11
18
  import type { AnthropicInput } from '@langchain/anthropic';
12
- import type { OpenAIInput } from '@langchain/openai';
19
+ import type { ChatOllamaInput } from '@langchain/ollama';
13
20
  import { Providers } from '@/common';
14
21
 
15
- export type OpenAIClientOptions = Partial<OpenAIInput>;
16
- export type AnthropicClientOptions = Partial<AnthropicInput>;
17
- export type MistralAIClientOptions = Partial<ChatMistralAIInput>;
18
- export type VertexAIClientOptions = Partial<ChatVertexAIInput>;
19
- export type BedrockClientOptions = Partial<BedrockChatFields>;
20
- export type BedrockConverseClientOptions = Partial<ChatBedrockConverseInput>;
22
+ export type ChatOpenAIToolType = BindToolsInput | OpenAIClient.ChatCompletionTool;
23
+ export type CommonToolType = StructuredTool | ChatOpenAIToolType;
21
24
 
22
- export type ClientOptions =
23
- | OpenAIClientOptions
24
- | AnthropicClientOptions
25
- | MistralAIClientOptions
26
- | VertexAIClientOptions
27
- | BedrockClientOptions
28
- | BedrockConverseClientOptions;
25
+ export type OpenAIClientOptions = ChatOpenAIFields;
26
+ export type OllamaClientOptions = ChatOllamaInput;
27
+ export type AnthropicClientOptions = AnthropicInput;
28
+ export type MistralAIClientOptions = ChatMistralAIInput;
29
+ export type VertexAIClientOptions = ChatVertexAIInput;
30
+ export type BedrockClientOptions = BedrockChatFields;
31
+ export type BedrockConverseClientOptions = ChatBedrockConverseInput;
29
32
 
30
- export type ChatModel = typeof ChatAnthropic | typeof ChatOpenAI | typeof ChatMistralAI | typeof ChatVertexAI | typeof BedrockChat | typeof ChatBedrockConverse;
33
+ export type ClientOptions = OpenAIClientOptions | OllamaClientOptions | AnthropicClientOptions | MistralAIClientOptions | VertexAIClientOptions | BedrockClientOptions | BedrockConverseClientOptions;
31
34
 
32
35
  export type LLMConfig = {
33
36
  provider: Providers;
34
37
  } & ClientOptions;
35
38
 
36
- export type ChatModelInstance = ChatOpenAI | ChatAnthropic | ChatMistralAI | ChatVertexAI | BedrockChat | ChatBedrockConverse;
39
+ export type ProviderOptionsMap = {
40
+ [Providers.OPENAI]: OpenAIClientOptions;
41
+ [Providers.OLLAMA]: OllamaClientOptions;
42
+ [Providers.ANTHROPIC]: AnthropicClientOptions;
43
+ [Providers.MISTRALAI]: MistralAIClientOptions;
44
+ [Providers.VERTEXAI]: VertexAIClientOptions;
45
+ [Providers.BEDROCK_LEGACY]: BedrockClientOptions;
46
+ [Providers.BEDROCK]: BedrockConverseClientOptions;
47
+ };
37
48
 
38
- export type ChatModelConstructor = new (config: ClientOptions) => ChatModelInstance;
49
+ export type ChatModelMap = {
50
+ [Providers.OPENAI]: ChatOpenAI;
51
+ [Providers.OLLAMA]: ChatOllama;
52
+ [Providers.ANTHROPIC]: ChatAnthropic;
53
+ [Providers.MISTRALAI]: ChatMistralAI;
54
+ [Providers.VERTEXAI]: ChatVertexAI;
55
+ [Providers.BEDROCK_LEGACY]: BedrockChat;
56
+ [Providers.BEDROCK]: ChatBedrockConverse;
57
+ };
58
+
59
+ export type ChatModelConstructorMap = {
60
+ [P in Providers]: new (config: ProviderOptionsMap[P]) => ChatModelMap[P];
61
+ };
62
+
63
+ export type ChatModelInstance = ChatModelMap[Providers];
64
+
65
+ export type ModelWithTools = ChatModelInstance & {
66
+ bindTools(tools: CommonToolType[]): Runnable;
67
+ }
@@ -10,6 +10,13 @@ const llmConfigs: Record<string, t.LLMConfig | undefined> = {
10
10
  streaming: true,
11
11
  streamUsage: true,
12
12
  },
13
+ [Providers.OLLAMA]: {
14
+ provider: Providers.OLLAMA,
15
+ model: 'llama3.2',
16
+ streaming: true,
17
+ streamUsage: true,
18
+ baseUrl: 'http://host.docker.internal:11434'
19
+ },
13
20
  [Providers.ANTHROPIC]: {
14
21
  provider: Providers.ANTHROPIC,
15
22
  model: 'claude-3-5-sonnet-20240620',
@@ -43,7 +50,7 @@ const llmConfigs: Record<string, t.LLMConfig | undefined> = {
43
50
 
44
51
  export function getLLMConfig(provider: string): t.LLMConfig {
45
52
  const config = llmConfigs[provider];
46
- if (!config) {
53
+ if (config === undefined) {
47
54
  throw new Error(`Unsupported provider: ${provider}`);
48
55
  }
49
56
  return config;