mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-01-25 11:46:12 +01:00
🚀 feat: Agent Cache Tokens & Anthropic Reasoning Support (#6098)
* fix: handling of top_k and top_p parameters for Claude-3.7 models (allowed without reasoning) * feat: bump @librechat/agents for Anthropic Reasoning support * fix: update reasoning handling for OpenRouter integration * fix: enhance agent token spending logic to include cache creation and read details * fix: update logic for thinking status in ContentParts component * refactor: improve agent title handling * chore: bump @librechat/agents to version 2.1.7 for parallel tool calling for Google models
This commit is contained in:
parent
34f967eff8
commit
9802629848
11 changed files with 187 additions and 40 deletions
|
|
@ -746,15 +746,6 @@ class AnthropicClient extends BaseClient {
|
|||
metadata,
|
||||
};
|
||||
|
||||
if (!/claude-3[-.]7/.test(model)) {
|
||||
if (top_p !== undefined) {
|
||||
requestOptions.top_p = top_p;
|
||||
}
|
||||
if (top_k !== undefined) {
|
||||
requestOptions.top_k = top_k;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.useMessages) {
|
||||
requestOptions.messages = payload;
|
||||
requestOptions.max_tokens =
|
||||
|
|
@ -769,6 +760,14 @@ class AnthropicClient extends BaseClient {
|
|||
thinkingBudget: this.options.thinkingBudget,
|
||||
});
|
||||
|
||||
if (!/claude-3[-.]7/.test(model)) {
|
||||
requestOptions.top_p = top_p;
|
||||
requestOptions.top_k = top_k;
|
||||
} else if (requestOptions.thinking == null) {
|
||||
requestOptions.topP = top_p;
|
||||
requestOptions.topK = top_k;
|
||||
}
|
||||
|
||||
if (this.systemMessage && this.supportsCacheControl === true) {
|
||||
requestOptions.system = [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1309,6 +1309,12 @@ ${convo}
|
|||
modelOptions.include_reasoning = true;
|
||||
reasoningKey = 'reasoning';
|
||||
}
|
||||
if (this.useOpenRouter && modelOptions.reasoning_effort != null) {
|
||||
modelOptions.reasoning = {
|
||||
effort: modelOptions.reasoning_effort,
|
||||
};
|
||||
delete modelOptions.reasoning_effort;
|
||||
}
|
||||
|
||||
this.streamHandler = new SplitStreamHandler({
|
||||
reasoningKey,
|
||||
|
|
|
|||
|
|
@ -680,4 +680,53 @@ describe('AnthropicClient', () => {
|
|||
expect(capturedOptions).not.toHaveProperty('top_p');
|
||||
});
|
||||
});
|
||||
|
||||
it('should include top_k and top_p parameters for Claude-3.7 models when thinking is explicitly disabled', async () => {
|
||||
const client = new AnthropicClient('test-api-key', {
|
||||
modelOptions: {
|
||||
model: 'claude-3-7-sonnet',
|
||||
temperature: 0.7,
|
||||
topK: 10,
|
||||
topP: 0.9,
|
||||
},
|
||||
thinking: false,
|
||||
});
|
||||
|
||||
async function* mockAsyncGenerator() {
|
||||
yield { type: 'message_start', message: { usage: {} } };
|
||||
yield { delta: { text: 'Test response' } };
|
||||
yield { type: 'message_delta', usage: {} };
|
||||
}
|
||||
|
||||
jest.spyOn(client, 'createResponse').mockImplementation(() => {
|
||||
return mockAsyncGenerator();
|
||||
});
|
||||
|
||||
let capturedOptions = null;
|
||||
jest.spyOn(client, 'getClient').mockImplementation((options) => {
|
||||
capturedOptions = options;
|
||||
return {};
|
||||
});
|
||||
|
||||
const payload = [{ role: 'user', content: 'Test message' }];
|
||||
await client.sendCompletion(payload, {});
|
||||
|
||||
expect(capturedOptions).toHaveProperty('topK', 10);
|
||||
expect(capturedOptions).toHaveProperty('topP', 0.9);
|
||||
|
||||
client.setOptions({
|
||||
modelOptions: {
|
||||
model: 'claude-3.7-sonnet',
|
||||
temperature: 0.7,
|
||||
topK: 10,
|
||||
topP: 0.9,
|
||||
},
|
||||
thinking: false,
|
||||
});
|
||||
|
||||
await client.sendCompletion(payload, {});
|
||||
|
||||
expect(capturedOptions).toHaveProperty('topK', 10);
|
||||
expect(capturedOptions).toHaveProperty('topP', 0.9);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue