
打开油猴,粘贴脚本 后 访问即可
// ==UserScript==
// @name DeepSeek Usage 缓存命中率展示
// @namespace http://tampermonkey.net/
// @version 6.0
// @description 支持中英文切换,完美恢复顶部与悬浮窗的缓存命中率显示
// @author Your Name
// @match https://platform.deepseek.com/usage*
// @run-at document-start
// @grant none
// ==/UserScript==
(function() {
'use strict';
console.log("DeepSeek Usage 缓存命中率");
window.__ds_usage_map = {};
window.__ds_usage_days = [];
const originalFetch = window.fetch;
window.fetch = async function(...args) {
const response = await originalFetch.apply(this, args);
try {
const url = args[0] instanceof Request ? args[0].url : (typeof args[0] === 'string' ? args[0] : '');
if (url.includes('/api/v0/usage/amount')) {
const clone = response.clone();
clone.json().then(data => extractAndDisplayHitRate(data)).catch(() => {});
}
} catch (e) {}
return response;
};
const originalXhrOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url) {
this.addEventListener('load', function() {
if (typeof url === 'string' && url.includes('/api/v0/usage/amount')) {
try { extractAndDisplayHitRate(JSON.parse(this.responseText)); } catch(e) {}
}
});
originalXhrOpen.apply(this, arguments);
};
function extractAndDisplayHitRate(payload) {
try {
const totals = payload?.data?.biz_data?.total;
if (Array.isArray(totals)) {
let newMap = {};
for (const modelData of totals) {
if (!Array.isArray(modelData.usage)) continue;
let totalHit = 0; let totalMiss = 0; let totalResponse = 0; let totalTokens = 0;
for (const item of modelData.usage) {
const amount = parseInt(item.amount || '0', 10);
if (item.type === 'PROMPT_CACHE_HIT_TOKEN') { totalHit += amount; totalTokens += amount; }
else if (item.type === 'PROMPT_CACHE_MISS_TOKEN') { totalMiss += amount; totalTokens += amount; }
else if (item.type === 'RESPONSE_TOKEN') { totalResponse += amount; totalTokens += amount; }
else if (item.type === 'PROMPT_TOKEN') { totalTokens += amount; }
}
const totalPrompt = totalHit + totalMiss;
const hitRate = totalPrompt > 0 ? ((totalHit / totalPrompt) * 100).toFixed(2) : '0.00';
const rawNumberKey = totalTokens.toString();
newMap[rawNumberKey] = { model: modelData.model, hitRate, totalHit, totalMiss, totalResponse };
}
window.__ds_usage_map = newMap;
}
const days = payload?.data?.biz_data?.days;
if (Array.isArray(days)) {
window.__ds_usage_days = days;
}
} catch (e) {}
}
// 顶部整体注入
setInterval(() => {
const map = window.__ds_usage_map;
if (Object.keys(map).length === 0) return;
const spans = document.querySelectorAll('span.ds-text--lsp');
for (let span of spans) {
// "Tokens" 这个词在中文版也没有翻译,依然是 Tokens,所以这里不用改
if (span.textContent.trim() === 'Tokens') {
const container = span.parentElement;
const numberSpan = span.nextElementSibling;
if (!numberSpan) continue;
const uiTokenKey = numberSpan.textContent.replace(/,/g, '').replace(/\s/g, '');
const data = map[uiTokenKey];
if (data) {
let existingBadge = container.querySelector('.ds-injected-hit-rate');
const titleText = `模型: ${data.model}\n------------------------\n【输入 Tokens】\n✅ 命中: ${data.totalHit.toLocaleString()} \n❌ 未命中: ${data.totalMiss.toLocaleString()}\n【输出 Tokens】\n📤 模型生成: ${data.totalResponse.toLocaleString()}`;
if (!existingBadge || !document.body.contains(existingBadge)) {
existingBadge = document.createElement('span');
existingBadge.className = 'ds-injected-hit-rate ds-text ds-text--label2 ds-text--fsp ds-text--lsp';
existingBadge.style.cssText = 'color:#10B981; background-color:rgba(16, 185, 129, 0.15); padding:2px 8px; border-radius:12px; margin-left:12px; cursor:help;';
container.appendChild(existingBadge);
}
if (existingBadge.dataset.rate !== data.hitRate) {
existingBadge.dataset.rate = data.hitRate;
existingBadge.textContent = `命中率: ${data.hitRate}%`;
existingBadge.title = titleText;
}
}
}
}
}, 500);
// 悬浮窗指纹核对算法
function initTooltipEnhancer() {
setInterval(() => {
const divs = document.getElementsByTagName('div');
let tooltipDiv = null;
for (let i = divs.length - 1; i >= 0; i--) {
const div = divs[i];
const text = div.textContent;
// 【核心兼容】:同时支持检测英文的 "Input (Cache hit)" 和 中文的 "命中缓存"
if (!text || (!text.includes('Input (Cache hit)') && !text.includes('命中缓存'))) continue;
if (text.length > 300) continue;
if (div.style.position === 'absolute' || div.style.position === 'fixed' || div.style.zIndex) {
tooltipDiv = div;
break;
}
}
if (tooltipDiv) {
const text = tooltipDiv.textContent;
// 把弹窗里看到的所有数字全抓出来,放进“指纹袋”
const rawNumbers = (text.match(/[\d,]+/g) || []).map(n => parseInt(n.replace(/,/g, ''), 10));
const numberBag = new Set(rawNumbers);
const dateMatch = text.match(/\d{4}-\d{2}-\d{2}/);
const hoverDate = dateMatch ? dateMatch[0] : null;
let matchedHit = -1;
let matchedMiss = -1;
const days = window.__ds_usage_days || [];
for (const day of days) {
if (hoverDate && day.date !== hoverDate) continue;
for (const modelData of day.data) {
let hit = 0, miss = 0;
if (Array.isArray(modelData.usage)) {
for (const u of modelData.usage) {
if (u.type === 'PROMPT_CACHE_HIT_TOKEN') hit = parseInt(u.amount);
if (u.type === 'PROMPT_CACHE_MISS_TOKEN') miss = parseInt(u.amount);
}
}
if (numberBag.has(hit) && numberBag.has(miss)) {
matchedHit = hit;
matchedMiss = miss;
if (hit > 0 || miss > 0) break;
}
}
if (matchedHit > 0 || matchedMiss > 0) break;
}
if (matchedHit !== -1) {
const total = matchedHit + matchedMiss;
const hitRate = total > 0 ? ((matchedHit / total) * 100).toFixed(2) : '0.00';
let ourDiv = tooltipDiv.querySelector('.ds-tooltip-hit-rate');
if (!ourDiv || !tooltipDiv.contains(ourDiv)) {
ourDiv = document.createElement('div');
ourDiv.className = 'ds-tooltip-hit-rate';
ourDiv.style.cssText = 'margin-top: 6px; padding-top: 6px; border-top: 1px dashed rgba(255, 255, 255, 0.3); display: flex; align-items: center; justify-content: space-between; font-size: 14px; pointer-events: none; width: 100%;';
const leftSpan = document.createElement('span');
leftSpan.style.color = '#999';
leftSpan.textContent = '单日命中率';
const rightSpan = document.createElement('span');
rightSpan.className = 'ds-tooltip-rate-value';
rightSpan.style.cssText = 'color: #10B981; font-weight: bold; margin-left: auto; padding-left: 20px;';
ourDiv.appendChild(leftSpan);
ourDiv.appendChild(rightSpan);
tooltipDiv.appendChild(ourDiv);
}
const rightSpan = ourDiv.querySelector('.ds-tooltip-rate-value');
if (rightSpan.textContent !== `${hitRate}%`) {
rightSpan.textContent = `${hitRate}%`;
}
}
}
}, 100);
}
initTooltipEnhancer();
})();
太强了,实用功能,手动马克
已学习,过目不忘
nice
感谢分享
感谢分享