Skip to content

Commit f1583cd

Browse files
fix(langchain/middleware): allow model strings in summarization middleware (langchain-ai#9292)
Co-authored-by: Christian Bromann <[email protected]>
1 parent 7a4a385 commit f1583cd

File tree

3 files changed

+61
-2
lines changed

3 files changed

+61
-2
lines changed

.changeset/chatty-spies-shine.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"langchain": patch
3+
---
4+
5+
allow for model strings in summarization middleware

libs/langchain/src/agents/middleware/summarization.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { REMOVE_ALL_MESSAGES } from "@langchain/langgraph";
1818
import { createMiddleware } from "../middleware.js";
1919
import { countTokensApproximately } from "./utils.js";
2020
import { hasToolCalls } from "../utils.js";
21+
import { initChatModel } from "../../chat_models/universal.js";
2122

2223
const DEFAULT_SUMMARY_PROMPT = `<role>
2324
Context Extraction Assistant
@@ -57,7 +58,7 @@ const SEARCH_RANGE_FOR_TOOL_PAIRS = 5;
5758
type TokenCounter = (messages: BaseMessage[]) => number | Promise<number>;
5859

5960
const contextSchema = z.object({
60-
model: z.custom<BaseLanguageModel>(),
61+
model: z.custom<string | BaseLanguageModel>(),
6162
maxTokensBeforeSummary: z.number().optional(),
6263
messagesToKeep: z.number().default(DEFAULT_MESSAGES_TO_KEEP),
6364
tokenCounter: z
@@ -148,6 +149,11 @@ export function summarizationMiddleware(
148149
} as InferInteropZodOutput<typeof contextSchema>;
149150
const { messages } = state;
150151

152+
const model =
153+
typeof config.model === "string"
154+
? await initChatModel(config.model)
155+
: config.model;
156+
151157
// Ensure all messages have IDs
152158
ensureMessageIds(messages);
153159

@@ -180,7 +186,7 @@ export function summarizationMiddleware(
180186

181187
const summary = await createSummary(
182188
messagesToSummarize,
183-
config.model,
189+
model,
184190
config.summaryPrompt,
185191
tokenCounter
186192
);

libs/langchain/src/agents/middleware/tests/summarization.test.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,42 @@ import {
66
SystemMessage,
77
ToolMessage,
88
} from "@langchain/core/messages";
9+
910
import { summarizationMiddleware } from "../summarization.js";
1011
import { countTokensApproximately } from "../utils.js";
1112
import { createAgent } from "../../index.js";
1213
import { FakeToolCallingChatModel } from "../../tests/utils.js";
1314

15+
// Mock @langchain/anthropic to test model string usage without requiring the built package
16+
vi.mock("@langchain/anthropic", async () => {
17+
const { AIMessage } = await import("@langchain/core/messages");
18+
return {
19+
ChatAnthropic: class MockChatAnthropic {
20+
lc_kwargs: Record<string, any>;
21+
22+
constructor(params?: any) {
23+
this.lc_kwargs = params || {};
24+
}
25+
26+
async invoke() {
27+
return new AIMessage({ content: "Mocked response" });
28+
}
29+
30+
getName() {
31+
return "ChatAnthropic";
32+
}
33+
34+
get _modelType() {
35+
return "chat-anthropic";
36+
}
37+
38+
get lc_runnable() {
39+
return true;
40+
}
41+
},
42+
};
43+
});
44+
1445
describe("summarizationMiddleware", () => {
1546
// Mock summarization model
1647
function createMockSummarizationModel() {
@@ -335,4 +366,21 @@ describe("summarizationMiddleware", () => {
335366
expect(nonSystemMessages.length).toBeGreaterThanOrEqual(messagesToKeep);
336367
expect(nonSystemMessages.length).toBeLessThanOrEqual(messagesToKeep + 3); // Some buffer for safety
337368
});
369+
370+
it("can be created using a model string", async () => {
371+
const model = "anthropic:claude-sonnet-4-20250514";
372+
const middleware = summarizationMiddleware({
373+
model,
374+
maxTokensBeforeSummary: 100,
375+
messagesToKeep: 2,
376+
});
377+
378+
const agent = createAgent({
379+
model,
380+
middleware: [middleware],
381+
});
382+
383+
const result = await agent.invoke({ messages: [] });
384+
expect(result.messages.at(-1)?.content).toBe("Mocked response");
385+
});
338386
});

0 commit comments

Comments
 (0)