Compare commits
4 Commits
feature-ad
...
v1.1.0
Author | SHA1 | Date | |
---|---|---|---|
9ce7d47b8a | |||
69629b1eb3 | |||
09526242ff | |||
d2b6d7bd3f |
@ -21,8 +21,9 @@ cna=LI8HIAirQyACAWrg3cNOjH8F; _gcl_au=1.1.1200556497.1736728490; xlly_s=1; acw_t
|
|||||||
- **历史记录**:保存每次识别的结果和图片,方便查看。
|
- **历史记录**:保存每次识别的结果和图片,方便查看。
|
||||||
- **一键复制**:轻松复制识别结果到剪贴板。
|
- **一键复制**:轻松复制识别结果到剪贴板。
|
||||||
- **数学公式识别**:特别优化了对数学公式的提取,支持 LaTeX 格式输出。
|
- **数学公式识别**:特别优化了对数学公式的提取,支持 LaTeX 格式输出。
|
||||||
- **API 支持**:提供 `curl` 接口调用,支持通过图片文件、base64 和图片 URL 3种方式。(Apifox调用文档示例(仅作为代码示例,尝试本地调试):https://we4q3dzb3r.apifox.cn/)
|
- **API 支持**:提供 `curl` 接口调用,支持通过图片文件、base64 和图片 URL 3种方式。(Apifox调用文档示例(**仅作为代码示例,尝试本地调试**):https://we4q3dzb3r.apifox.cn/)
|
||||||
- **验证码识别**:新增验证码识别功能,支持常见类型的验证码(如数字、字母、混合字符等),提升自动化处理能力。
|
- **验证码识别**:新增验证码识别功能,支持常见类型的验证码(如数字、字母、混合字符等),提升自动化处理能力。
|
||||||
|
- **自定义prompt**: 在高级模式下(v1.1.0支持),用户可以自定义 prompt,跳过格式化处理,直接返回原始结果,而在普通模式下,使用默认的 prompt 并保持现有的格式化处理逻辑。
|
||||||
## 🛠️ 部署指南
|
## 🛠️ 部署指南
|
||||||
|
|
||||||
### 1. 部署到 Cloudflare Workers
|
### 1. 部署到 Cloudflare Workers
|
||||||
|
175
worker.js
175
worker.js
@ -252,6 +252,37 @@ async function handleProxyUpload(request) {
|
|||||||
// 通用的识别函数
|
// 通用的识别函数
|
||||||
async function recognizeImage(token, imageId, request) {
|
async function recognizeImage(token, imageId, request) {
|
||||||
const cookie = request.headers.get('x-custom-cookie') || '';
|
const cookie = request.headers.get('x-custom-cookie') || '';
|
||||||
|
|
||||||
|
// 从请求头中获取高级模式状态和自定义prompt
|
||||||
|
const advancedMode = request.headers.get('x-advanced-mode') === 'true';
|
||||||
|
|
||||||
|
// 解码自定义prompt
|
||||||
|
let customPrompt = '';
|
||||||
|
try {
|
||||||
|
const encodedPrompt = request.headers.get('x-custom-prompt');
|
||||||
|
if (encodedPrompt) {
|
||||||
|
customPrompt = decodeURIComponent(atob(encodedPrompt));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Prompt解码错误:', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultPrompt = '请识别图片中的内容,注意以下要求:\n' +
|
||||||
|
'对于数学公式和普通文本:\n' +
|
||||||
|
'1. 所有数学公式和数学符号都必须使用标准的LaTeX格式\n' +
|
||||||
|
'2. 行内公式使用单个$符号包裹,如:$x^2$\n' +
|
||||||
|
'3. 独立公式块使用两个$$符号包裹,如:$$\\sum_{i=1}^n i^2$$\n' +
|
||||||
|
'4. 普通文本保持原样,不要使用LaTeX格式\n' +
|
||||||
|
'5. 保持原文的段落格式和换行\n' +
|
||||||
|
'6. 明显的换行使用\\n表示\n' +
|
||||||
|
'7. 确保所有数学符号都被正确包裹在$或$$中\n\n' +
|
||||||
|
'对于验证码图片:\n' +
|
||||||
|
'1. 只输出验证码字符,不要加任何额外解释\n' +
|
||||||
|
'2. 忽略干扰线和噪点\n' +
|
||||||
|
'3. 注意区分相似字符,如0和O、1和l、2和Z等\n' +
|
||||||
|
'4. 验证码通常为4-6位字母数字组合\n\n' +
|
||||||
|
'不要输出任何额外的解释或说明';
|
||||||
|
|
||||||
const response = await fetch('https://chat.qwenlm.ai/api/chat/completions', {
|
const response = await fetch('https://chat.qwenlm.ai/api/chat/completions', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
@ -271,21 +302,7 @@ async function recognizeImage(token, imageId, request) {
|
|||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
text: '请识别图片中的内容,注意以下要求:\n' +
|
text: advancedMode ? customPrompt : defaultPrompt,
|
||||||
'对于数学公式和普通文本:\n' +
|
|
||||||
'1. 所有数学公式和数学符号都必须使用标准的LaTeX格式\n' +
|
|
||||||
'2. 行内公式使用单个$符号包裹,如:$x^2$\n' +
|
|
||||||
'3. 独立公式块使用两个$$符号包裹,如:$$\\sum_{i=1}^n i^2$$\n' +
|
|
||||||
'4. 普通文本保持原样,不要使用LaTeX格式\n' +
|
|
||||||
'5. 保持原文的段落格式和换行\n' +
|
|
||||||
'6. 明显的换行使用\\n表示\n' +
|
|
||||||
'7. 确保所有数学符号都被正确包裹在$或$$中\n\n' +
|
|
||||||
'对于验证码图片:\n' +
|
|
||||||
'1. 只输出验证码字符,不要加任何额外解释\n' +
|
|
||||||
'2. 忽略干扰线和噪点\n' +
|
|
||||||
'3. 注意区分相似字符,如0和O、1和l、2和Z等\n' +
|
|
||||||
'4. 验证码通常为4-6位字母数字组合\n\n' +
|
|
||||||
'不要输出任何额外的解释或说明',
|
|
||||||
chat_type: "t2t"
|
chat_type: "t2t"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -305,30 +322,33 @@ async function recognizeImage(token, imageId, request) {
|
|||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
let result = data.choices[0]?.message?.content || '识别失败';
|
let result = data.choices[0]?.message?.content || '识别失败';
|
||||||
|
|
||||||
// 如果结果长度小于10且只包含字母数字,很可能是验证码
|
// 只在非高级模式下进行格式化处理
|
||||||
if (result.length <= 10 && /^[A-Za-z0-9]+$/.test(result)) {
|
if (!advancedMode) {
|
||||||
return new Response(JSON.stringify({
|
// 如果结果长度小于10且只包含字母数字,很可能是验证码
|
||||||
success: true,
|
if (result.length <= 10 && /^[A-Za-z0-9]+$/.test(result)) {
|
||||||
result: result.toUpperCase(), // 验证码统一转大写
|
return new Response(JSON.stringify({
|
||||||
type: 'captcha'
|
success: true,
|
||||||
}), {
|
result: result.toUpperCase(),
|
||||||
headers: {
|
type: 'captcha'
|
||||||
'Content-Type': 'application/json',
|
}), {
|
||||||
'Access-Control-Allow-Origin': '*',
|
headers: {
|
||||||
},
|
'Content-Type': 'application/json',
|
||||||
});
|
'Access-Control-Allow-Origin': '*',
|
||||||
}
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 其他情况(数学公式和普通文本)的处理
|
// 其他情况(数学公式和普通文本)的处理
|
||||||
result = result
|
result = result
|
||||||
.replace(/\\(/g, '\\(')
|
.replace(/\\(/g, '\\(')
|
||||||
.replace(/\\)/g, '\\)')
|
.replace(/\\)/g, '\\)')
|
||||||
.replace(/\n{3,}/g, '\n\n')
|
.replace(/\n{3,}/g, '\n\n')
|
||||||
.replace(/([^\n])\n([^\n])/g, '$1\n$2')
|
.replace(/([^\n])\n([^\n])/g, '$1\n$2')
|
||||||
.replace(/\$\s+/g, '$')
|
.replace(/\$\s+/g, '$')
|
||||||
.replace(/\s+\$/g, '$')
|
.replace(/\s+\$/g, '$')
|
||||||
.replace(/\$\$/g, '$$')
|
.replace(/\$\$/g, '$$')
|
||||||
.trim();
|
.trim();
|
||||||
|
}
|
||||||
|
|
||||||
return new Response(JSON.stringify({
|
return new Response(JSON.stringify({
|
||||||
success: true,
|
success: true,
|
||||||
@ -1183,8 +1203,8 @@ function getHTML() {
|
|||||||
// 添加获取cookie按钮样式
|
// 添加获取cookie按钮样式
|
||||||
' .get-cookie-link {',
|
' .get-cookie-link {',
|
||||||
' position: fixed;',
|
' position: fixed;',
|
||||||
' right: 200px;', // 放在github图标左边
|
' left: 150px;', // 放在github图标左边
|
||||||
' top: 20px;',
|
' top: 22px;',
|
||||||
' background: #2ecc71;', // 使用不同的颜色区分
|
' background: #2ecc71;', // 使用不同的颜色区分
|
||||||
' color: white;',
|
' color: white;',
|
||||||
' border: none;',
|
' border: none;',
|
||||||
@ -1199,6 +1219,45 @@ function getHTML() {
|
|||||||
|
|
||||||
' .get-cookie-link:hover {',
|
' .get-cookie-link:hover {',
|
||||||
' background: #27ae60;',
|
' background: #27ae60;',
|
||||||
|
' }',
|
||||||
|
|
||||||
|
' .advanced-mode-toggle {',
|
||||||
|
' display: flex;',
|
||||||
|
' align-items: center;',
|
||||||
|
' margin-bottom: 15px;',
|
||||||
|
' padding: 10px;',
|
||||||
|
' background: #f8f9fa;',
|
||||||
|
' border-radius: 8px;',
|
||||||
|
' }',
|
||||||
|
|
||||||
|
' .advanced-mode-toggle input[type="checkbox"] {',
|
||||||
|
' margin-right: 10px;',
|
||||||
|
' }',
|
||||||
|
|
||||||
|
' .prompt-container {',
|
||||||
|
' display: none;', // 默认隐藏
|
||||||
|
' margin-bottom: 15px;',
|
||||||
|
' }',
|
||||||
|
|
||||||
|
' .prompt-container.show {',
|
||||||
|
' display: block;',
|
||||||
|
' }',
|
||||||
|
|
||||||
|
' #promptInput {',
|
||||||
|
' width: 100%;',
|
||||||
|
' padding: 12px;',
|
||||||
|
' border: 2px solid #e9ecef;',
|
||||||
|
' border-radius: 8px;',
|
||||||
|
' font-size: 0.95rem;',
|
||||||
|
' resize: vertical;',
|
||||||
|
' min-height: 120px;',
|
||||||
|
' font-family: monospace;',
|
||||||
|
' line-height: 1.4;',
|
||||||
|
' }',
|
||||||
|
|
||||||
|
' #promptInput:focus {',
|
||||||
|
' outline: none;',
|
||||||
|
' border-color: #3498db;',
|
||||||
' }',
|
' }',
|
||||||
'</style>',
|
'</style>',
|
||||||
'</head>',
|
'</head>',
|
||||||
@ -1229,6 +1288,14 @@ function getHTML() {
|
|||||||
'</div>',
|
'</div>',
|
||||||
// 添加 tokenList 容器
|
// 添加 tokenList 容器
|
||||||
'<div class="token-list" id="tokenList"></div>', // 添加这一行
|
'<div class="token-list" id="tokenList"></div>', // 添加这一行
|
||||||
|
'<div class="advanced-mode-toggle">',
|
||||||
|
' <input type="checkbox" id="advancedMode">',
|
||||||
|
' <label for="advancedMode">高级模式 (自定义Prompt)</label>',
|
||||||
|
'</div>',
|
||||||
|
'<div class="prompt-container" id="promptContainer">',
|
||||||
|
' <label for="promptInput">自定义Prompt</label>',
|
||||||
|
' <textarea id="promptInput" placeholder="输入自定义prompt...">请识别图片中的内容,注意以下要求:\n对于数学公式和普通文本:\n1. 所有数学公式和数学符号都必须使用标准的LaTeX格式\n2. 行内公式使用单个$符号包裹,如:$x^2$\n3. 独立公式块使用两个$$符号包裹,如:$$\\sum_{i=1}^n i^2$$\n4. 普通文本保持原样,不要使用LaTeX格式\n5. 保持原文的段落格式和换行\n6. 明显的换行使用\\n表示\n7. 确保所有数学符号都被正确包裹在$或$$中\n\n对于验证码图片:\n1. 只输出验证码字符,不要加任何额外解释\n2. 忽略干扰线和噪点\n3. 注意区分相似字符,如0和O、1和l、2和Z等\n4. 验证码通常为4-6位字母数字组合\n\n不要输出任何额外的解释或说明</textarea>',
|
||||||
|
'</div>',
|
||||||
'</div>',
|
'</div>',
|
||||||
|
|
||||||
'<div class="container">',
|
'<div class="container">',
|
||||||
@ -1521,6 +1588,8 @@ function getHTML() {
|
|||||||
' headers: { ',
|
' headers: { ',
|
||||||
' \'Content-Type\': \'application/json\',',
|
' \'Content-Type\': \'application/json\',',
|
||||||
' \'x-custom-cookie\': savedCookie,',
|
' \'x-custom-cookie\': savedCookie,',
|
||||||
|
' \'x-advanced-mode\': advancedMode.checked, // 添加高级模式状态',
|
||||||
|
' \'x-custom-prompt\': btoa(encodeURIComponent(promptInput.value)), // Base64编码',
|
||||||
' },',
|
' },',
|
||||||
' body: JSON.stringify({ imageId: uploadData.id }),',
|
' body: JSON.stringify({ imageId: uploadData.id }),',
|
||||||
' });',
|
' });',
|
||||||
@ -1925,6 +1994,32 @@ function getHTML() {
|
|||||||
|
|
||||||
' // 初始化时调用loadSettings',
|
' // 初始化时调用loadSettings',
|
||||||
' loadSettings();',
|
' loadSettings();',
|
||||||
|
|
||||||
|
' // 高级模式切换处理',
|
||||||
|
' const advancedMode = document.getElementById(\'advancedMode\');',
|
||||||
|
' const promptContainer = document.getElementById(\'promptContainer\');',
|
||||||
|
' const promptInput = document.getElementById(\'promptInput\');',
|
||||||
|
|
||||||
|
' advancedMode.addEventListener(\'change\', () => {',
|
||||||
|
' promptContainer.classList.toggle(\'show\', advancedMode.checked);',
|
||||||
|
' localStorage.setItem(\'advancedMode\', advancedMode.checked);',
|
||||||
|
' localStorage.setItem(\'customPrompt\', promptInput.value);',
|
||||||
|
' });',
|
||||||
|
|
||||||
|
' // 加载保存的高级模式设置',
|
||||||
|
' function loadAdvancedSettings() {',
|
||||||
|
' const savedMode = localStorage.getItem(\'advancedMode\');',
|
||||||
|
' const savedPrompt = localStorage.getItem(\'customPrompt\');',
|
||||||
|
' if (savedMode === \'true\') {',
|
||||||
|
' advancedMode.checked = true;',
|
||||||
|
' promptContainer.classList.add(\'show\');',
|
||||||
|
' }',
|
||||||
|
' if (savedPrompt) {',
|
||||||
|
' promptInput.value = savedPrompt;',
|
||||||
|
' }',
|
||||||
|
' }',
|
||||||
|
|
||||||
|
' loadAdvancedSettings();',
|
||||||
'</script>',
|
'</script>',
|
||||||
'</body>',
|
'</body>',
|
||||||
'</html>'
|
'</html>'
|
||||||
|
Reference in New Issue
Block a user