Adding Claude caching support to OpenRouter as well

befe5a7171e62517cb6cd985a37eafb9a58f1d11

Honey Tree <kalakanlogs@proton.me>

1 files changed, +44 -3Showing whitespace changes
src/endpoints/backends/chat-completions.js+44 -3
@@ -80,9 +80,9 @@ async function sendClaudeRequest(request, response) {
80 const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.CLAUDE);80 const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.CLAUDE);
81 const divider = '-'.repeat(process.stdout.columns);81 const divider = '-'.repeat(process.stdout.columns);
82 const enableSystemPromptCache = getConfigValue('claude.enableSystemPromptCache', false) && request.body.model.startsWith('claude-3');82 const enableSystemPromptCache = getConfigValue('claude.enableSystemPromptCache', false) && request.body.model.startsWith('claude-3');
83 let cachingAtDepth = getConfigValue('claude.cachingAtDepth', -1) && request.body.model.startsWith('claude-3');83 let cachingAtDepth = getConfigValue('claude.cachingAtDepth', -1);
84 // Disabled if not an integer or negative84 // Disabled if not an integer or negative, or if the model doesn't support it
85 if (!Number.isInteger(cachingAtDepth) || cachingAtDepth < 0) {85 if (!Number.isInteger(cachingAtDepth) || cachingAtDepth < 0 || !request.body.model.startsWith('claude-3')) {
86 cachingAtDepth = -1;86 cachingAtDepth = -1;
87 }87 }
8888
@@ -899,6 +899,47 @@ router.post('/generate', jsonParser, function (request, response) {
899 if (request.body.use_fallback) {899 if (request.body.use_fallback) {
900 bodyParams['route'] = 'fallback';900 bodyParams['route'] = 'fallback';
901 }901 }
902
903 let cachingAtDepth = getConfigValue('claude.cachingAtDepth', -1);
904 if (Number.isInteger(cachingAtDepth) && cachingAtDepth >= 0 && request.body.model.startsWith('anthropic/claude-3')) {
905 //caching the prefill is a terrible idea in general
906 let passedThePrefill = false;
907 //depth here is the number of message role switches
908 let depth = 0;
909 let previousRoleName = "";
910 for (let i = request.body.messages.length - 1; i >= 0; i--) {
911 if (!passedThePrefill && request.body.messages[i].role === 'assistant') {
912 continue;
913 }
914
915 passedThePrefill = true;
916
917 if (request.body.messages[i].role !== previousRoleName) {
918 if (depth === cachingAtDepth || depth === cachingAtDepth + 2) {
919 const content = request.body.messages[i].content;
920 if (typeof content === 'string') {
921 request.body.messages[i].content = [{
922 type: 'text',
923 text: content,
924 cache_control: { type: "ephemeral"},
925 }];
926 } else {
927 const contentPartCount = content.length;
928 content[contentPartCount - 1].cache_control = {
929 type: "ephemeral"
930 }
931 }
932 }
933
934 if (depth === cachingAtDepth + 2) {
935 break
936 }
937
938 depth += 1;
939 previousRoleName = request.body.messages[i].role;
940 }
941 }
942 }
902 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.CUSTOM) {943 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.CUSTOM) {
903 apiUrl = request.body.custom_url;944 apiUrl = request.body.custom_url;
904 apiKey = readSecret(request.user.directories, SECRET_KEYS.CUSTOM);945 apiKey = readSecret(request.user.directories, SECRET_KEYS.CUSTOM);