├── .gitignore ├── LICENSE ├── README.md ├── README_EN.md ├── cf_workers_version.js ├── index.html ├── package.json ├── postcss.config.js ├── src ├── App.vue ├── assets │ └── icon.svg ├── data │ ├── descriptions.json │ ├── examples.json │ └── prompts.json ├── index.css ├── main.js └── views │ └── Home.vue ├── tailwind.config.js └── vite.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules/ 3 | npm-debug.log* 4 | yarn-debug.log* 5 | yarn-error.log* 6 | package-lock.json 7 | yarn.lock 8 | 9 | # Build outputs 10 | dist/ 11 | build/ 12 | .next/ 13 | out/ 14 | .specstory 15 | 16 | # Environment variables 17 | .env 18 | .env.local 19 | .env.*.local 20 | .cursorignore 21 | # IDE and editor files 22 | .idea/ 23 | .vscode/ 24 | *.swp 25 | *.swo 26 | .DS_Store 27 | 28 | # Logs 29 | logs/ 30 | *.log 31 | 32 | # Coverage directory 33 | coverage/ 34 | 35 | # Cache directories 36 | .cache/ 37 | .npm/ 38 | .eslintcache -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 reverse-check 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🔍 reverse-check:LLM API 逆向检测工具 2 | **当前版本:v0.02** 3 | 4 | [English Version](./README_EN.md) | 中文版 5 | 6 | **项目地址**:[GitHub](https://github.com/star5o/reverse-check) | [网站1(vercel域名)](https://reverse-check.vercel.app/) | [网站2(我的域名)](https://reverse-check.no-reverse-api.com) 7 | 8 | **Vercel一键部署**:[![使用 Vercel 部署](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/star5o/Freverse-check&project-name=reverse-check&repository-name=reverse-check) 9 | 10 | 本工具是一个基于是否支持官方参数的逆向检测工具。不能通过本工具检测的API极大概率是逆向的。 11 | 12 | 目前项目处于初步阶段,暂时需要人工对比响应结果与示例进行判断。 13 | 14 | ## 功能特性 15 | 16 | - 🔍 支持多种模型提供商的API检测 17 | - OpenAI 18 | - Claude 19 | - Gemini 20 | 21 | - 🛠 丰富的参数测试选项 22 | - max_tokens参数检测 23 | - logprobs参数检测 24 | - n参数检测 25 | - stop参数检测 26 | - function_call/tools参数检测 27 | - response_format参数检测 28 | - 图像输入检测 29 | 30 | - 📊 直观的结果展示 31 | - API请求信息实时展示 32 | - 响应结果对比分析 33 | - 官方示例参考 34 | - 简洁/完整响应切换 35 | 36 | ## 技术栈 37 | 38 | - 前端框架:Vue 3 39 | - UI组件:Tailwind CSS 40 | - 构建工具:Vite 41 | 42 | ## 手动部署 43 | 44 | ### 安装依赖 45 | 46 | ```bash 47 | npm install 48 | ``` 49 | 50 | ### 运行开发服务器 51 | 52 | ```bash 53 | npm run dev 54 | ``` 55 | 56 | ### 构建生产版本 57 | 58 | ```bash 59 | npm run build 60 | ``` 61 | 62 | ## 使用说明 63 | 64 | 1. 选择模型提供商(OpenAI/Claude/Gemini) 65 | 2. 选择要测试的参数类型 66 | 3. 填写API配置信息 67 | - API Base URL 68 | - API Key 69 | - 模型名称 70 | 4. 点击「开始检测」按钮 71 | 5. 查看检测结果和对比信息 72 | 73 | ## 参数详情 74 | 75 | ### OpenAI 参数 76 | 77 | | **参数** | **说明** | 78 | |------------------|--------------------------------------------------------------------------| 79 | | **max_tokens** | 官方API严格遵循token限制(如max_tokens=10),逆向API会忽略限制。 | 80 | | **logprobs** | 官方API会返回每个token的logprobs信息,逆向API不支持此功能。 | 81 | | **n** | 官方API可以返回多个答案(如n=2),逆向API只返回一个。 | 82 | | **stop** | 官方API会在遇到停止词时停止生成,逆向API会忽略停止词。 | 83 | | **image_url** | 官方API能正确处理图片URL并生成描述,逆向API无法处理图片。 | 84 | | **function_call**| 官方API返回JSON格式的函数调用,逆向API不调用函数。 | 85 | | **response_format**| 官方API返回指定格式(如JSON),逆向API只返回字符串。 | 86 | 87 | ### Claude 参数 88 | 89 | | **参数** | **说明** | 90 | |------------------|--------------------------------------------------------------------------| 91 | | **max_tokens** | 官方API严格遵循token限制(如max_tokens=10),逆向API会忽略限制。 | 92 | | **stop** | 官方API会在遇到停止词时停止生成,逆向API会忽略停止词。 | 93 | | **function_call**| 官方API返回JSON格式的函数调用,逆向API不调用函数。 | 94 | 95 | ### Gemini 参数 96 | 97 | | **参数** | **说明** | 98 | |------------------|--------------------------------------------------------------------------| 99 | | **max_tokens** | 官方API严格遵循token限制(如max_tokens=10),逆向API会忽略限制。 | 100 | | **codeExecution**| 官方API有内置的代码执行工具,逆向实现无法执行代码。 | 101 | | **googleSearch** | 官方API能正确调用Google搜索并返回结果,逆向实现无法使用Google搜索工具。 | 102 | | **response_format**| 官方API返回指定格式(如JSON),逆向实现只返回字符串。 | 103 | 104 | ## 待办事项 105 | 106 | 1. 实现自动化逆向检测 107 | 2. 实现与Uptime Kuma的集成以进行持续监控 108 | 109 | ## change log 110 | ### v0.0.2 111 | 1. 增加了推理模型专用检测参数 112 | - OpenAI: reasoning_max_tokens参数检测 113 | - Claude: reasoning_stop参数检测 114 | 2. 当API响应返回错误时(如520错误),也能在页面上显示完整的响应体,而不是弹窗提示。 115 | 116 | ## 推理模型说明 117 | OpenAI的 API 不会返回reasoning_content字段 118 | 119 | ## API文档参考 120 | 121 | - [OpenAI API文档](https://platform.openai.com/docs/api-reference/chat) 122 | - [Claude API文档](https://docs.anthropic.com/en/api/messages) 123 | - [Gemini API文档](https://ai.google.dev/gemini-api/docs) 124 | 125 | ## 许可证 126 | 127 | MIT License -------------------------------------------------------------------------------- /README_EN.md: -------------------------------------------------------------------------------- 1 | # 🔍 LLM API Reverse Engineering Detection Tool 2 | **Current Version: v0.02** 3 | 4 | [中文版](./README.md) | English Version 5 | 6 | **Project Links**: [GitHub](https://github.com/star5o/reverse-check) | [Website](https://reverse-check.vercel.app/) 7 | 8 | [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/star5o/Freverse-check&project-name=reverse-check&repository-name=reverse-check) 9 | 10 | This LLM API reverse engineering detection tool based on official parameter support. APIs that fail the detection are highly likely to be reverse-engineered. 11 | 12 | The project is currently in its initial phase, requiring manual comparison of response results with examples. 13 | 14 | ## Features 15 | 16 | - 🔍 Multi-Provider API Detection 17 | - OpenAI 18 | - Claude 19 | - Gemini 20 | 21 | - 🛠 Comprehensive Parameter Testing 22 | - max_tokens parameter validation 23 | - logprobs parameter testing 24 | - n parameter verification 25 | - stop sequence testing 26 | - function_call/tools parameter validation 27 | - response_format parameter testing 28 | - image input support testing 29 | 30 | - 📊 Intuitive Results Display 31 | - Real-time API request information 32 | - Response comparison analysis 33 | - Official examples reference 34 | - Toggle between concise/complete responses 35 | 36 | ## Tech Stack 37 | 38 | - Frontend Framework: Vue 3 39 | - UI Components: Tailwind CSS 40 | - Build Tool: Vite 41 | 42 | ## Quick Start 43 | 44 | ### Install Dependencies 45 | 46 | ```bash 47 | npm install 48 | ``` 49 | 50 | ### Run Development Server 51 | 52 | ```bash 53 | npm run dev 54 | ``` 55 | 56 | ### Build for Production 57 | 58 | ```bash 59 | npm run build 60 | ``` 61 | 62 | ## Usage Guide 63 | 64 | 1. Select a model provider (OpenAI/Claude/Gemini) 65 | 2. Choose parameter types to test 66 | 3. Configure API settings 67 | - API Base URL 68 | - API Key 69 | - Model name 70 | 4. Click "Start Detection" button 71 | 5. Review test results and comparison data 72 | 73 | ## Parameter Details 74 | 75 | ### OpenAI Parameters 76 | 77 | | **Parameter** | **Explanation** | 78 | |------------------|--------------------------------------------------------------------------| 79 | | **max_tokens** | Official API strictly follows token limits (e.g., max_tokens=10), reverse-engineered ones ignore limits. | 80 | | **logprobs** | Official API returns logprobs information for each token, reverse-engineered ones don't support it. | 81 | | **n** | Official API returns multiple answers (e.g., n=2), reverse-engineered ones only return one. | 82 | | **stop** | Official API stops generation at stop words, reverse-engineered ones ignore them. | 83 | | **image_url** | Official API properly processes image URLs and generates descriptions, reverse-engineered ones can't handle images. | 84 | | **function_call**| Official API returns JSON-formatted function calls, reverse-engineered ones don't call functions. | 85 | | **response_format**| Official API returns specified formats (like JSON), reverse-engineered ones only return strings. | 86 | 87 | ### Claude Parameters 88 | 89 | | **Parameter** | **Explanation** | 90 | |------------------|--------------------------------------------------------------------------| 91 | | **max_tokens** | Official API strictly follows token limits (e.g., max_tokens=10), reverse-engineered ones ignore limits. | 92 | | **stop** | Official API stops generation at stop words, reverse-engineered ones ignore them. | 93 | | **function_call**| Official API returns JSON-formatted function calls, reverse-engineered ones don't call functions. | 94 | 95 | ### Gemini Parameters 96 | 97 | | **Parameter** | **Explanation** | 98 | |------------------|--------------------------------------------------------------------------| 99 | | **max_tokens** | Official API strictly follows token limits (e.g., max_tokens=10), reverse-engineered ones ignore limits. | 100 | | **codeExecution**| Official API has built-in code execution tools, reverse-engineered implementations can't execute code. | 101 | | **googleSearch** | Official API correctly calls Google Search and returns results, reverse-engineered implementations can't use Google Search tool. | 102 | | **response_format**| Official API returns specified formats (like JSON), reverse-engineered implementations only return strings. | 103 | 104 | 105 | ## TODO 106 | 107 | 1. Implement automated reverse engineering detection 108 | 2. Implement integration with Uptime Kuma for continuous monitoring 109 | 110 | ## Changelog 111 | ### v0.02 112 | 1. Added reasoning model specific detection parameters 113 | - OpenAI: reasoning_max_tokens parameter testing 114 | - Claude: reasoning_stop parameter testing 115 | - Gemini: reasoning_max_tokens parameter testing 116 | 2. Fixed error handling to display complete response body on API errors (e.g., 520 errors) instead of showing popup alerts. 117 | 118 | ## API Documentation References 119 | 120 | - [OpenAI API Documentation](https://platform.openai.com/docs/api-reference/chat) 121 | - [Claude API Documentation](https://docs.anthropic.com/en/api/messages) 122 | - [Gemini API Documentation](https://ai.google.dev/gemini-api/docs) 123 | 124 | ## License 125 | 126 | MIT License -------------------------------------------------------------------------------- /cf_workers_version.js: -------------------------------------------------------------------------------- 1 | const HTML_CONTENT = ` 2 | 3 | 4 | 5 | 6 | 7 | 逆向与否 8 | 9 | 10 | 11 |
12 |

逆向与否

13 | 14 |
15 | 16 |
17 |
18 |
19 | 20 | 22 |
23 | 24 |
25 | 26 | 27 |
28 | 29 |
30 | 31 | 32 |
33 | 34 |
35 | 36 | 42 |
43 | 44 | 47 |
48 |
49 | 50 | 51 |
52 |

响应结果:

53 |

 54 |                 
55 | 58 | 61 |
62 |
63 |
64 | 65 | 66 |
67 | 68 |
69 |

逆向接口返回示例:

70 |

 71 |             
72 | 73 | 74 |
75 |

官方接口返回示例:

76 |

 77 |             
78 |
79 |
80 | 81 | 321 | 322 | 323 | `; 324 | 325 | async function handleApiTest(request) { 326 | const { baseUrl, apiKey, model, testType } = await request.json(); 327 | 328 | // 添加 https:// 前缀(如果用户没有输入) 329 | const fullBaseUrl = baseUrl.startsWith('http') ? baseUrl : `https://${baseUrl}`; 330 | 331 | let requestBody = { 332 | model: model, 333 | messages: [{ 334 | role: "user", 335 | content: "repeat ' deepseek number 1 ' 20 times" 336 | }] 337 | }; 338 | 339 | // 根据测试类型添加相应参数 340 | switch(testType) { 341 | case 'max_tokens': 342 | requestBody.max_tokens = 9; 343 | break; 344 | case 'logprobs': 345 | requestBody.logprobs = true; 346 | break; 347 | case 'n': 348 | requestBody.n = 2; 349 | break; 350 | case 'stop': 351 | requestBody.stop = ["stop"]; 352 | break; 353 | } 354 | 355 | try { 356 | const response = await fetch(`${fullBaseUrl}/v1/chat/completions`, { 357 | method: 'POST', 358 | headers: { 359 | 'Content-Type': 'application/json', 360 | 'Authorization': `Bearer ${apiKey}` 361 | }, 362 | body: JSON.stringify(requestBody) 363 | }); 364 | 365 | const data = await response.json(); 366 | return new Response(JSON.stringify(data), { 367 | headers: { 'Content-Type': 'application/json' } 368 | }); 369 | } catch (error) { 370 | return new Response(JSON.stringify({ error: error.message }), { 371 | status: 500, 372 | headers: { 'Content-Type': 'application/json' } 373 | }); 374 | } 375 | } 376 | 377 | async function handleRequest(request) { 378 | const url = new URL(request.url); 379 | 380 | if (url.pathname === '/api_request' && request.method === 'POST') { 381 | return handleApiTest(request); 382 | } 383 | 384 | // 返回主页 385 | return new Response(HTML_CONTENT, { 386 | headers: { 'Content-Type': 'text/html' } 387 | }); 388 | } 389 | 390 | addEventListener('fetch', event => { 391 | event.respondWith(handleRequest(event.request)); 392 | }); 393 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 逆向与否 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reverse-check", 3 | "private": true, 4 | "version": "0.0.1", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@ant-design/icons-vue": "^7.0.1", 13 | "@vercel/analytics": "^1.5.0", 14 | "@vueuse/core": "^10.6.1", 15 | "ant-design-vue": "^4.0.7", 16 | "vue": "^3.3.8", 17 | "vue-i18n": "^9.8.0", 18 | "vue-router": "^4.2.5" 19 | }, 20 | "devDependencies": { 21 | "@vitejs/plugin-vue": "^4.5.0", 22 | "autoprefixer": "^10.4.16", 23 | "postcss": "^8.4.31", 24 | "tailwindcss": "^3.3.0", 25 | "vite": "^5.0.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /src/assets/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/data/descriptions.json: -------------------------------------------------------------------------------- 1 | { 2 | "openai": { 3 | "max_tokens": { 4 | "title": "max_tokens 参数检测说明", 5 | "description": "此检测通过设置较小的 max_tokens 值(10)来观察模型的输出限制处理。官方API会严格遵守token限制,而逆向会忽略此限制。", 6 | "focus_points": [ 7 | "官方API:输出将严格限制在10个token以内", 8 | "逆向API:会遵循prompt输出完整的重复内容,超过token限制", 9 | "当前prompt:'输出 'deepseek number 1' 5次'", 10 | "检测参数设置:max_tokens=10" 11 | ] 12 | }, 13 | "reasoning_max_tokens": { 14 | "title": "推理模型专用 max_tokens 参数检测说明", 15 | "description": "此检测针对推理模型(如o1等),通过设置较小的max_tokens值(10)观察模型输出限制。官方API会严格遵守token限制,而逆向会完整输出响应内容。", 16 | "focus_points": [ 17 | "官方API:message.content内容为空或极短", 18 | "逆向API:message.content会生成完整内容", 19 | "当前prompt:输出 'deepseek number 1' 5次", 20 | "检测参数设置:max_tokens=10" 21 | ] 22 | }, 23 | "logprobs": { 24 | "title": "logprobs 参数检测说明", 25 | "description": "此参数在官方API中支持,而逆向实现会不支持该参数。", 26 | "focus_points": [ 27 | "官方API:会返回每一个token的logprobs信息,也就是每个token的概率", 28 | "逆向API:只会回答prompt的问题,不会返回logprobs信息", 29 | "当前prompt:'hello!", 30 | "检测参数设置:logprobs=true,top_logprobs=2" 31 | ] 32 | }, 33 | "n": { 34 | "title": "n 参数检测说明", 35 | "description": "通过设置n=2测试模型是否能正确返回多个不同的回答。官方API会返回两个回答,而逆向实现只会返回一个回答。", 36 | "focus_points": [ 37 | "官方API:返回两个回答", 38 | "逆向API:返回一个回答", 39 | "当前prompt:'Hello!'", 40 | "检测参数设置:n=2" 41 | ] 42 | }, 43 | "stop": { 44 | "title": "stop 参数检测说明", 45 | "description": "测试模型是否正确实现了停止序列功能。当遇到停止词时,官方API会立即停止生成,而逆向会忽略此参数输出完整内容。", 46 | "focus_points": [ 47 | "官方API:遇到'4'时会立即停止生成", 48 | "逆向API:会生成完整的数字序列", 49 | "当前prompt:'Count from 1 to 10'" 50 | ] 51 | }, 52 | "image_url": { 53 | "title": "image_url 参数检测说明", 54 | "description": "测试模型对图像URL输入的处理能力。官方API能正确处理图像输入并生成相关描述,而逆向实现可能无法处理或返回错误。", 55 | "focus_points": [ 56 | "官方API:能正确解析图像并生成相关描述", 57 | "逆向API:可能无法处理图像URL或返回错误信息", 58 | "当前prompt:'这是一张什么图片'", 59 | "image_url: https://www.google.com/images/branding/googlelogo/1x/googlelogo_light_color_272x92dp.png", 60 | "注意!image_url参数已被大多数中转商单独处理,带image_url参数的请求走官方渠道(或通过逆向脚本上传图片),所以该参数检测结果不可信" 61 | ] 62 | }, 63 | "function_call": { 64 | "title": "function_call 参数检测说明", 65 | "description": "测试模型对函数调用的处理能力。官方API能准确解析和执行函数调用,而逆向就不会调用函数。", 66 | "focus_points": [ 67 | "官方API:准确返回函数执行的参数", 68 | "逆向API:不会使用函数调用", 69 | "当前prompt:'Whats the weather like in Boston today?'", 70 | "注意!function_call参数已被众多中转商单独处理,带function_call参数的请求走官方渠道,所以该参数检测结果不可信" 71 | ] 72 | }, 73 | "response_format": { 74 | "title": "response_format 参数检测说明", 75 | "description": "测试模型对响应格式的支持。官方API能正确返回指定格式的响应,而逆向只会返回字符串。", 76 | "focus_points": [ 77 | "官方API:返回为json格式", 78 | "逆向API:普通字符串格式", 79 | "当前prompt:'给我一个名字和年龄吧'", 80 | "注意!response_format参数已被某些中转商单独处理,带response_format参数的请求走官方渠道,所以该参数检测结果不可信" 81 | ] 82 | } 83 | }, 84 | "claude": { 85 | "max_tokens": { 86 | "title": "max_tokens 参数检测说明", 87 | "description": "此检测通过设置较小的 max_tokens 值(10)来观察模型的输出限制处理。官方API会严格遵守token限制,而逆向实现可能会忽略此限制。", 88 | "focus_points": [ 89 | "官方API:输出将严格限制在10个token以内", 90 | "逆向API:会遵循prompt输出完整的重复内容,超过token限制", 91 | "当前prompt:'输出 'deepseek number 1' 5次'", 92 | "检测参数设置:max_tokens=10" 93 | ] 94 | }, 95 | "reasoning_stop": { 96 | "title": "推理模型专用 stop 参数检测说明", 97 | "description": "此检测针对Claude推理模型,通过设置stop参数为['3']观察模型的推理过程如何展示。官方API会在消息内容中正确停止生成,推理内容不受影响。", 98 | "focus_points": [ 99 | "官方API:message.content内容不含有字符'3'", 100 | "逆向API:message.content内容包含完整数字序列,包括'3'", 101 | "当前prompt:'Count from 1 to 10 with Arabic numerals'", 102 | "检测参数设置:stop=['3']" 103 | ] 104 | }, 105 | "stop": { 106 | "title": "stop 参数检测说明", 107 | "description": "测试模型是否正确实现了停止序列功能。当遇到停止词时,官方API会立即停止生成,而逆向会忽略此参数输出完整内容。", 108 | "focus_points": [ 109 | "官方API:遇到'4'时会立即停止生成", 110 | "逆向API:会生成完整的数字序列", 111 | "当前prompt:'Count from 1 to 10'" 112 | ] 113 | }, 114 | "function_call": { 115 | "title": "tools 参数检测说明", 116 | "description": "测试模型对函数调用的处理能力。官方API能准确解析和执行函数调用,而逆向就不会调用函数。", 117 | "focus_points": [ 118 | "官方API:准确返回函数执行的参数", 119 | "逆向API:不会使用函数调用", 120 | "当前prompt:'Whats the weather like in Boston today?'", 121 | "注意!tools参数已被众多中转商单独处理,带tools参数的请求走官方渠道,所以该参数检测结果不可信" 122 | ] 123 | } 124 | }, 125 | "gemini": { 126 | "max_tokens": { 127 | "title": "max_tokens 参数检测说明", 128 | "description": "此检测通过设置较小的 max_tokens 值(10)来观察模型的输出限制处理。官方API会严格遵守token限制,而逆向实现可能会忽略此限制。", 129 | "focus_points": [ 130 | "官方API:输出将严格限制在10个token以内", 131 | "逆向API:会遵循prompt输出完整的重复内容,超过token限制", 132 | "当前prompt:'输出 'deepseek number 1' 5次'", 133 | "检测参数设置:max_tokens=10" 134 | ] 135 | }, 136 | "codeExecution": { 137 | "title": "codeExecution 参数检测说明", 138 | "description": "Gemini官方的API内置代码执行工具,会自动编写并执行代码,然后基于代码执行结果进行回答。", 139 | "focus_points": [ 140 | "官方API:因为执行了代码,所以结果比较准确,为5117", 141 | "逆向API:可能是其他数字", 142 | "当前prompt:要求前50个指数的和,即'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50'" 143 | ] 144 | }, 145 | "googleSearch": { 146 | "title": "googleSearch 参数检测说明", 147 | "description": "Gemini官方的API内置谷歌搜索工具。官方API能正确返回调用谷歌搜索后的结果。", 148 | "focus_points": [ 149 | "官方API:会返回今天的日期", 150 | "逆向API:不为今天的日期", 151 | "当前prompt:'今天是几月几号'" 152 | ] 153 | }, 154 | "response_format": { 155 | "title": "response_format 参数检测说明", 156 | "description": "测试模型对响应格式的支持。官方API能正确返回指定格式的响应,而逆向只会返回字符串。", 157 | "focus_points": [ 158 | "官方API:返回为json格式", 159 | "逆向API:普通字符串格式", 160 | "当前prompt:'给我一个名字和年龄吧'", 161 | "注意!response_format参数已被某些中转商单独处理,带response_format参数的请求走官方渠道,所以该参数检测结果不可信" 162 | ] 163 | } 164 | } 165 | } -------------------------------------------------------------------------------- /src/data/examples.json: -------------------------------------------------------------------------------- 1 | { 2 | "openai": { 3 | "max_tokens": { 4 | "reverse": { 5 | "id": "chatcmpl-5478735d-4e52-492a-935e-5d2f5e2bd664", 6 | "object": "chat.completion", 7 | "created": 1740733120, 8 | "system_fingerprint": "fp_494464e1cbeb", 9 | "choices": [ 10 | { 11 | "index": 0, 12 | "message": { 13 | "role": "assistant", 14 | "content": "deepseek number 1 \ndeepseek number 1 \ndeepseek number 1 \ndeepseek number 1 \ndeepseek number 1 " 15 | }, 16 | "finish_reason": "stop" 17 | } 18 | ], 19 | "usage": { 20 | "prompt_tokens": 11, 21 | "completion_tokens": 30, 22 | "total_tokens": 41 23 | } 24 | }, 25 | "official": { 26 | "id": "chatcmpl-B5ciMnnnBD4JOKqlxqbV6Ju4mw3nn", 27 | "object": "chat.completion", 28 | "created": 1740680158, 29 | "model": "gpt-4o-2024-11-20", 30 | "choices": [ 31 | { 32 | "index": 0, 33 | "message": { 34 | "role": "assistant", 35 | "content": "好的,以下是输出 `'deepseek number ", 36 | "refusal": null 37 | }, 38 | "logprobs": null, 39 | "finish_reason": "length" 40 | } 41 | ], 42 | "usage": { 43 | "prompt_tokens": 18, 44 | "completion_tokens": 10, 45 | "total_tokens": 28, 46 | "prompt_tokens_details": { 47 | "cached_tokens": 0, 48 | "audio_tokens": 0 49 | }, 50 | "completion_tokens_details": { 51 | "reasoning_tokens": 0, 52 | "audio_tokens": 0, 53 | "accepted_prediction_tokens": 0, 54 | "rejected_prediction_tokens": 0 55 | } 56 | }, 57 | "service_tier": "default", 58 | "system_fingerprint": "fp_178d5ba2c0" 59 | } 60 | }, 61 | "logprobs": { 62 | "reverse": { 63 | "id": "chatcmpl-a8cf55be-a34a-4a8f-8342-2646ac4ceff5", 64 | "object": "chat.completion", 65 | "created": 1740733338, 66 | "model": "gpt-4o", 67 | "provider": "NiansuhAI", 68 | "system_fingerprint": "fp_4151a65e5332", 69 | "choices": [ 70 | { 71 | "index": 0, 72 | "message": { 73 | "role": "assistant", 74 | "content": "Hello! How can I assist you today?" 75 | }, 76 | "finish_reason": "stop" 77 | } 78 | ], 79 | "usage": { 80 | "prompt_tokens": 2, 81 | "completion_tokens": 9, 82 | "total_tokens": 11 83 | } 84 | }, 85 | "official": { 86 | "id": "chatcmpl-B5qYR17RXblmgllUhW1FMGFb40pnY", 87 | "object": "chat.completion", 88 | "created": 1740733359, 89 | "model": "gpt-4o-2024-08-06", 90 | "choices": [ 91 | { 92 | "index": 0, 93 | "message": { 94 | "role": "assistant", 95 | "content": "Hello! How can I assist you today?", 96 | "refusal": null 97 | }, 98 | "logprobs": { 99 | "content": [ 100 | { 101 | "token": "Hello", 102 | "logprob": -0.47408080101013184, 103 | "bytes": [ 104 | 72, 105 | 101, 106 | 108, 107 | 108, 108 | 111 109 | ], 110 | "top_logprobs": [ 111 | { 112 | "token": "Hello", 113 | "logprob": -0.47408080101013184, 114 | "bytes": [ 115 | 72, 116 | 101, 117 | 108, 118 | 108, 119 | 111 120 | ] 121 | }, 122 | { 123 | "token": "Hi", 124 | "logprob": -0.9740808010101318, 125 | "bytes": [ 126 | 72, 127 | 105 128 | ] 129 | } 130 | ] 131 | }, 132 | { 133 | "token": "!", 134 | "logprob": -0.0000062729995988775045, 135 | "bytes": [ 136 | 33 137 | ], 138 | "top_logprobs": [ 139 | { 140 | "token": "!", 141 | "logprob": -0.0000062729995988775045, 142 | "bytes": [ 143 | 33 144 | ] 145 | }, 146 | { 147 | "token": " there", 148 | "logprob": -12.000006675720215, 149 | "bytes": [ 150 | 32, 151 | 116, 152 | 104, 153 | 101, 154 | 114, 155 | 101 156 | ] 157 | } 158 | ] 159 | }, 160 | { 161 | "token": " How", 162 | "logprob": -0.0000018624639324116288, 163 | "bytes": [ 164 | 32, 165 | 72, 166 | 111, 167 | 119 168 | ], 169 | "top_logprobs": [ 170 | { 171 | "token": " How", 172 | "logprob": -0.0000018624639324116288, 173 | "bytes": [ 174 | 32, 175 | 72, 176 | 111, 177 | 119 178 | ] 179 | }, 180 | { 181 | "token": " What", 182 | "logprob": -13.250001907348633, 183 | "bytes": [ 184 | 32, 185 | 87, 186 | 104, 187 | 97, 188 | 116 189 | ] 190 | } 191 | ] 192 | }, 193 | { 194 | "token": " can", 195 | "logprob": -0.000003531315314830863, 196 | "bytes": [ 197 | 32, 198 | 99, 199 | 97, 200 | 110 201 | ], 202 | "top_logprobs": [ 203 | { 204 | "token": " can", 205 | "logprob": -0.000003531315314830863, 206 | "bytes": [ 207 | 32, 208 | 99, 209 | 97, 210 | 110 211 | ] 212 | }, 213 | { 214 | "token": " may", 215 | "logprob": -12.625003814697266, 216 | "bytes": [ 217 | 32, 218 | 109, 219 | 97, 220 | 121 221 | ] 222 | } 223 | ] 224 | }, 225 | { 226 | "token": " I", 227 | "logprob": 0, 228 | "bytes": [ 229 | 32, 230 | 73 231 | ], 232 | "top_logprobs": [ 233 | { 234 | "token": " I", 235 | "logprob": 0, 236 | "bytes": [ 237 | 32, 238 | 73 239 | ] 240 | }, 241 | { 242 | "token": " assist", 243 | "logprob": -23.5, 244 | "bytes": [ 245 | 32, 246 | 97, 247 | 115, 248 | 115, 249 | 105, 250 | 115, 251 | 116 252 | ] 253 | } 254 | ] 255 | }, 256 | { 257 | "token": " assist", 258 | "logprob": -0.0021852378267794847, 259 | "bytes": [ 260 | 32, 261 | 97, 262 | 115, 263 | 115, 264 | 105, 265 | 115, 266 | 116 267 | ], 268 | "top_logprobs": [ 269 | { 270 | "token": " assist", 271 | "logprob": -0.0021852378267794847, 272 | "bytes": [ 273 | 32, 274 | 97, 275 | 115, 276 | 115, 277 | 105, 278 | 115, 279 | 116 280 | ] 281 | }, 282 | { 283 | "token": " help", 284 | "logprob": -6.127185344696045, 285 | "bytes": [ 286 | 32, 287 | 104, 288 | 101, 289 | 108, 290 | 112 291 | ] 292 | } 293 | ] 294 | }, 295 | { 296 | "token": " you", 297 | "logprob": 0, 298 | "bytes": [ 299 | 32, 300 | 121, 301 | 111, 302 | 117 303 | ], 304 | "top_logprobs": [ 305 | { 306 | "token": " you", 307 | "logprob": 0, 308 | "bytes": [ 309 | 32, 310 | 121, 311 | 111, 312 | 117 313 | ] 314 | }, 315 | { 316 | "token": " today", 317 | "logprob": -24.125, 318 | "bytes": [ 319 | 32, 320 | 116, 321 | 111, 322 | 100, 323 | 97, 324 | 121 325 | ] 326 | } 327 | ] 328 | }, 329 | { 330 | "token": " today", 331 | "logprob": 0, 332 | "bytes": [ 333 | 32, 334 | 116, 335 | 111, 336 | 100, 337 | 97, 338 | 121 339 | ], 340 | "top_logprobs": [ 341 | { 342 | "token": " today", 343 | "logprob": 0, 344 | "bytes": [ 345 | 32, 346 | 116, 347 | 111, 348 | 100, 349 | 97, 350 | 121 351 | ] 352 | }, 353 | { 354 | "token": "?", 355 | "logprob": -18.5, 356 | "bytes": [ 357 | 63 358 | ] 359 | } 360 | ] 361 | }, 362 | { 363 | "token": "?", 364 | "logprob": -6.704273118884885e-7, 365 | "bytes": [ 366 | 63 367 | ], 368 | "top_logprobs": [ 369 | { 370 | "token": "?", 371 | "logprob": -6.704273118884885e-7, 372 | "bytes": [ 373 | 63 374 | ] 375 | }, 376 | { 377 | "token": "?\n", 378 | "logprob": -14.250000953674316, 379 | "bytes": [ 380 | 63, 381 | 10 382 | ] 383 | } 384 | ] 385 | } 386 | ], 387 | "refusal": null 388 | }, 389 | "finish_reason": "stop" 390 | } 391 | ], 392 | "usage": { 393 | "prompt_tokens": 9, 394 | "completion_tokens": 10, 395 | "total_tokens": 19, 396 | "prompt_tokens_details": { 397 | "cached_tokens": 0, 398 | "audio_tokens": 0 399 | }, 400 | "completion_tokens_details": { 401 | "reasoning_tokens": 0, 402 | "audio_tokens": 0, 403 | "accepted_prediction_tokens": 0, 404 | "rejected_prediction_tokens": 0 405 | } 406 | }, 407 | "service_tier": "default", 408 | "system_fingerprint": "fp_eb9dce56a8" 409 | } 410 | }, 411 | "function_call": { 412 | "reverse": { 413 | "id": "chatcmpl-123", 414 | "object": "chat.completion", 415 | "created": 1677652288, 416 | "choices": [ 417 | { 418 | "index": 0, 419 | "message": { 420 | "role": "assistant", 421 | "content": "I'm unable to provide real-time information, including current weather conditions. However, you can easily check the weather in Boston today by using a weather website like Weather.com or a weather app on your smartphone. Alternatively, you can ask a voice assistant like Siri, Google Assistant, or Alexa for the latest updates. Let me know if you'd like help with anything else!" 422 | } 423 | } 424 | ] 425 | }, 426 | "official": { 427 | "id": "chatcmpl-B5oYcSyY7aWHMWXZ5Fv3ZA8984P38", 428 | "object": "chat.completion", 429 | "created": 1740725682, 430 | "model": "gpt-4o-2024-11-20", 431 | "choices": [ 432 | { 433 | "index": 0, 434 | "message": { 435 | "role": "assistant", 436 | "content": null, 437 | "tool_calls": [ 438 | { 439 | "id": "call_sZxRdvpwKMvwyJtj6NMVDVzz", 440 | "type": "function", 441 | "function": { 442 | "name": "get_current_weather", 443 | "arguments": "{\"location\":\"Boston, MA\"}" 444 | } 445 | } 446 | ], 447 | "refusal": null 448 | }, 449 | "logprobs": null, 450 | "finish_reason": "tool_calls" 451 | } 452 | ], 453 | "usage": { 454 | "prompt_tokens": 80, 455 | "completion_tokens": 18, 456 | "total_tokens": 98, 457 | "prompt_tokens_details": { 458 | "cached_tokens": 0, 459 | "audio_tokens": 0 460 | }, 461 | "completion_tokens_details": { 462 | "reasoning_tokens": 0, 463 | "audio_tokens": 0, 464 | "accepted_prediction_tokens": 0, 465 | "rejected_prediction_tokens": 0 466 | } 467 | }, 468 | "service_tier": "default", 469 | "system_fingerprint": "fp_7c1f2cecc3" 470 | } 471 | }, 472 | "response_format": { 473 | "reverse": { 474 | "id": "chatcmpl-ROdemkVP3dCjKqoarimhx09pnpqQ0", 475 | "object": "chat.completion", 476 | "created": 1740729771, 477 | "model": "gpt-4o-2024-11-20", 478 | "choices": [ 479 | { 480 | "index": 0, 481 | "message": { 482 | "role": "assistant", 483 | "content": "好的,我给你取一个名字叫 **晨曦**,寓意着清晨的第一缕阳光,充满希望和活力。年龄的话,就设定为 **25 岁**,正值青春年华,充满无限可能!😊", 484 | "refusal": null 485 | }, 486 | "logprobs": null, 487 | "finish_reason": "stop" 488 | } 489 | ], 490 | "usage": { 491 | "prompt_tokens": 0, 492 | "completion_tokens": 0, 493 | "total_tokens": 0, 494 | "prompt_tokens_details": { 495 | "cached_tokens": 0, 496 | "audio_tokens": 0 497 | }, 498 | "completion_tokens_details": { 499 | "reasoning_tokens": 0, 500 | "audio_tokens": 0, 501 | "accepted_prediction_tokens": 0, 502 | "rejected_prediction_tokens": 0 503 | } 504 | }, 505 | "system_fingerprint": "fp_6807a54d31" 506 | }, 507 | "official": { 508 | "id": "chatcmpl-B5pcqTv3SEQcQUIFZTG3INF4dl30I", 509 | "object": "chat.completion", 510 | "created": 1740729788, 511 | "model": "gpt-4o-2024-11-20", 512 | "choices": [ 513 | { 514 | "index": 0, 515 | "message": { 516 | "role": "assistant", 517 | "content": "{\"name\":\"小明\",\"age\":25}", 518 | "refusal": null 519 | }, 520 | "logprobs": null, 521 | "finish_reason": "stop" 522 | } 523 | ], 524 | "usage": { 525 | "prompt_tokens": 51, 526 | "completion_tokens": 11, 527 | "total_tokens": 62, 528 | "prompt_tokens_details": { 529 | "cached_tokens": 0, 530 | "audio_tokens": 0 531 | }, 532 | "completion_tokens_details": { 533 | "reasoning_tokens": 0, 534 | "audio_tokens": 0, 535 | "accepted_prediction_tokens": 0, 536 | "rejected_prediction_tokens": 0 537 | } 538 | }, 539 | "service_tier": "default", 540 | "system_fingerprint": "fp_7c1f2cecc3" 541 | } 542 | }, 543 | "n": { 544 | "reverse": { 545 | "id": "chatcmpl-SRRSjviQNd1eCUHHQWbN4rumeX3ct", 546 | "object": "chat.completion", 547 | "created": 1740679079, 548 | "model": "gpt-4o-2024-11-20", 549 | "choices": [ 550 | { 551 | "index": 0, 552 | "message": { 553 | "role": "assistant", 554 | "content": "Got it! How can I assist you today? 😊", 555 | "refusal": null 556 | }, 557 | "logprobs": null, 558 | "finish_reason": "stop" 559 | } 560 | ], 561 | "usage": { 562 | "prompt_tokens": 0, 563 | "completion_tokens": 0, 564 | "total_tokens": 0, 565 | "prompt_tokens_details": { 566 | "cached_tokens": 0, 567 | "audio_tokens": 0 568 | }, 569 | "completion_tokens_details": { 570 | "reasoning_tokens": 0, 571 | "audio_tokens": 0, 572 | "accepted_prediction_tokens": 0, 573 | "rejected_prediction_tokens": 0 574 | } 575 | }, 576 | "system_fingerprint": "fp_45b1fb6a83" 577 | }, 578 | "official": { 579 | "id": "chatcmpl-B5cPnUjHj3f0s39DpKbu0xHA7ZCmS", 580 | "object": "chat.completion", 581 | "created": 1740679007, 582 | "model": "gpt-4o-2024-11-20", 583 | "choices": [ 584 | { 585 | "index": 0, 586 | "message": { 587 | "role": "assistant", 588 | "content": "Hello! 😊 How can I assist you today?", 589 | "refusal": null 590 | }, 591 | "logprobs": null, 592 | "finish_reason": "stop" 593 | }, 594 | { 595 | "index": 1, 596 | "message": { 597 | "role": "assistant", 598 | "content": "Hi there! How can I assist you today? 😊", 599 | "refusal": null 600 | }, 601 | "logprobs": null, 602 | "finish_reason": "stop" 603 | } 604 | ], 605 | "usage": { 606 | "prompt_tokens": 9, 607 | "completion_tokens": 23, 608 | "total_tokens": 32, 609 | "prompt_tokens_details": { 610 | "cached_tokens": 0, 611 | "audio_tokens": 0 612 | }, 613 | "completion_tokens_details": { 614 | "reasoning_tokens": 0, 615 | "audio_tokens": 0, 616 | "accepted_prediction_tokens": 0, 617 | "rejected_prediction_tokens": 0 618 | } 619 | }, 620 | "service_tier": "default", 621 | "system_fingerprint": "fp_4dd9e4e381" 622 | } 623 | }, 624 | "image_url": { 625 | "reverse": { 626 | "choices": [ 627 | { 628 | "finish_reason": "stop", 629 | "index": 0, 630 | "message": { 631 | "content": "很抱歉,我无法查看或分析图片。如果你能描述一下图片的内容或提供一些详细信息,我会尽力帮助你解答相关问题!", 632 | "role": "assistant" 633 | } 634 | } 635 | ], 636 | "created": 1740720538, 637 | "id": "chatcmpl-B5nDvCe77Y07LferKAyvNEa82ETAI", 638 | "model": "gpt-4o-2024-11-20", 639 | "object": "chat.completion", 640 | "usage": { 641 | "completion_tokens": 52, 642 | "prompt_tokens": 8, 643 | "total_tokens": 60 644 | } 645 | }, 646 | "official": { 647 | "id": "chatcmpl-B5ny062ZzdKkkR3lDxsTvFtvcjNXr", 648 | "object": "chat.completion", 649 | "created": 1740723412, 650 | "model": "gpt-4o-2024-11-20", 651 | "choices": [ 652 | { 653 | "index": 0, 654 | "message": { 655 | "role": "assistant", 656 | "content": "这是一张谷歌(Google)标志的图片。", 657 | "refusal": null 658 | }, 659 | "logprobs": null, 660 | "finish_reason": "stop" 661 | } 662 | ], 663 | "usage": { 664 | "prompt_tokens": 452, 665 | "completion_tokens": 14, 666 | "total_tokens": 466, 667 | "prompt_tokens_details": { 668 | "cached_tokens": 0, 669 | "audio_tokens": 0 670 | }, 671 | "completion_tokens_details": { 672 | "reasoning_tokens": 0, 673 | "audio_tokens": 0, 674 | "accepted_prediction_tokens": 0, 675 | "rejected_prediction_tokens": 0 676 | } 677 | }, 678 | "service_tier": "default", 679 | "system_fingerprint": "fp_4dd9e4e381" 680 | } 681 | }, 682 | "stop": { 683 | "reverse": { 684 | "id": "chatcmpl-bb5034c3-2e24-4ed1-b733-12e66505ce1a", 685 | "object": "chat.completion", 686 | "created": 1740734955, 687 | "system_fingerprint": "fp_d5139097a00d", 688 | "choices": [ 689 | { 690 | "index": 0, 691 | "message": { 692 | "role": "assistant", 693 | "content": "Sure! Here you go:\n\n1, 2, 3, 4, 5, 6, 7, 8, 9, 10." 694 | }, 695 | "finish_reason": "stop" 696 | } 697 | ], 698 | "usage": { 699 | "prompt_tokens": 7, 700 | "completion_tokens": 35, 701 | "total_tokens": 42 702 | } 703 | }, 704 | "official": { 705 | "id": "chatcmpl-B5cNThpGsSY90qFeJYEs1SkG6D073", 706 | "object": "chat.completion", 707 | "created": 1740678863, 708 | "model": "gpt-4o-2024-08-06", 709 | "choices": [ 710 | { 711 | "index": 0, 712 | "message": { 713 | "role": "assistant", 714 | "content": "Certainly! Here you go:\n\n1, 2, 3, ", 715 | "refusal": null 716 | }, 717 | "logprobs": null, 718 | "finish_reason": "stop" 719 | } 720 | ], 721 | "usage": { 722 | "prompt_tokens": 14, 723 | "completion_tokens": 15, 724 | "total_tokens": 29, 725 | "prompt_tokens_details": { 726 | "cached_tokens": 0, 727 | "audio_tokens": 0 728 | }, 729 | "completion_tokens_details": { 730 | "reasoning_tokens": 0, 731 | "audio_tokens": 0, 732 | "accepted_prediction_tokens": 0, 733 | "rejected_prediction_tokens": 0 734 | } 735 | }, 736 | "service_tier": "default", 737 | "system_fingerprint": "fp_b491d0b9e9" 738 | } 739 | }, 740 | "reasoning_max_tokens": { 741 | "reverse": { 742 | "id": "1c24e05b-b008-435a-9a93-6a14218b13c0", 743 | "object": "chat.completion", 744 | "created": 1743440167261, 745 | "model": "o3-mini", 746 | "choices": [ 747 | { 748 | "index": 0, 749 | "message": { 750 | "role": "assistant", 751 | "content": "## Thought:\n\n\n\nReasoned about output repetition for a few seconds\n\n\n\n## Answer:\n\ndeepseek number 1 \ndeepseek number 1 \ndeepseek number 1 \ndeepseek number 1 \ndeepseek number 1" 752 | }, 753 | "finish_reason": "stop" 754 | } 755 | ] 756 | }, 757 | "official": { 758 | "id": "gen-1743440107-lNK2x8KVMirOwk3NYukG", 759 | "provider": "OpenAI", 760 | "model": "openai/o3-mini", 761 | "object": "chat.completion", 762 | "created": 1743440107, 763 | "choices": [ 764 | { 765 | "logprobs": null, 766 | "finish_reason": "length", 767 | "native_finish_reason": "length", 768 | "index": 0, 769 | "message": { 770 | "role": "assistant", 771 | "content": "", 772 | "refusal": null 773 | } 774 | } 775 | ], 776 | "system_fingerprint": "fp_617f206dd9", 777 | "usage": { 778 | "prompt_tokens": 17, 779 | "completion_tokens": 10, 780 | "total_tokens": 27, 781 | "prompt_tokens_details": { 782 | "cached_tokens": 0 783 | }, 784 | "completion_tokens_details": { 785 | "reasoning_tokens": 10 786 | } 787 | } 788 | } 789 | } 790 | }, 791 | "claude": { 792 | "max_tokens": { 793 | "reverse": { 794 | "id": "chatcmpl-ac3e1f9d84a441e189f463d9e373b", 795 | "object": "chat.completion", 796 | "created": 1740740434, 797 | "model": "claude-3-5-sonnet-20241022", 798 | "system_fingerprint": "fp_a24b4d720c", 799 | "choices": [ 800 | { 801 | "index": 0, 802 | "message": { 803 | "role": "assistant", 804 | "content": "你可以通过简单的循环来实现这个输出。你可以想象一个循环结构,重复输出字符串 'deepseek number 1' 五次。每次循环都会打印这个字符串,直到达到五次为止。" 805 | }, 806 | "finish_reason": "stop" 807 | } 808 | ], 809 | "usage": { 810 | "prompt_tokens": 8, 811 | "completion_tokens": 23, 812 | "total_tokens": 31 813 | } 814 | }, 815 | "official": { 816 | "id": "chatcmpl-beiu3LcIeCg5JyJwebH650FToElv6", 817 | "object": "chat.completion", 818 | "created": 1740740337, 819 | "model": "claude-3-5-sonnet-20241022", 820 | "choices": [ 821 | { 822 | "index": 0, 823 | "message": { 824 | "role": "assistant", 825 | "content": "Here are 5 repetitions of '", 826 | "refusal": null 827 | }, 828 | "logprobs": null, 829 | "finish_reason": "stop" 830 | } 831 | ], 832 | "usage": { 833 | "prompt_tokens": 22, 834 | "completion_tokens": 10, 835 | "total_tokens": 32 836 | } 837 | } 838 | }, 839 | "stop": { 840 | "reverse": { 841 | "id": "chatcmpl-62b7e2cfd5a345b9b572182c8670b", 842 | "object": "chat.completion", 843 | "created": 1740740227, 844 | "model": "claude-3-5-sonnet-20241022", 845 | "system_fingerprint": "fp_a24b4d720c", 846 | "choices": [ 847 | { 848 | "index": 0, 849 | "message": { 850 | "role": "assistant", 851 | "content": "Here is the count from 1 to 10 using Arabic numerals:\n\n1, 2, 3, 4, 5, 6, 7, 8, 9, 10" 852 | }, 853 | "finish_reason": "stop" 854 | } 855 | ], 856 | "usage": { 857 | "prompt_tokens": 10, 858 | "completion_tokens": 23, 859 | "total_tokens": 33 860 | } 861 | }, 862 | "official": { 863 | "id": "chatcmpl-EG0noygvQICNxMc7oTJobFt9r09ZP", 864 | "object": "chat.completion", 865 | "created": 1740740283, 866 | "model": "claude-3-5-sonnet-20241022", 867 | "choices": [ 868 | { 869 | "index": 0, 870 | "message": { 871 | "role": "assistant", 872 | "content": "1\n2\n3\n", 873 | "refusal": null 874 | }, 875 | "logprobs": null, 876 | "finish_reason": "stop" 877 | } 878 | ], 879 | "usage": { 880 | "prompt_tokens": 20, 881 | "completion_tokens": 8, 882 | "total_tokens": 28 883 | } 884 | } 885 | }, 886 | "function_call": { 887 | "reverse": { 888 | "id": "chatcmpl-cf84c54e0443436fa0910dd982772", 889 | "object": "chat.completion", 890 | "created": 1740740119, 891 | "model": "claude-3-5-sonnet-20241022", 892 | "system_fingerprint": "fp_a24b4d720c", 893 | "choices": [ 894 | { 895 | "index": 0, 896 | "message": { 897 | "role": "assistant", 898 | "content": "I'm unable to provide real-time information such as current weather conditions. I recommend checking a reliable weather website or app for the latest updates on the weather in Boston." 899 | }, 900 | "finish_reason": "stop" 901 | } 902 | ], 903 | "usage": { 904 | "prompt_tokens": 10, 905 | "completion_tokens": 48, 906 | "total_tokens": 58 907 | } 908 | }, 909 | "official": { 910 | "id": "msg_bdrk_01QTe5d7DHQADTBXHDNAVrEH", 911 | "model": "claude-3-5-sonnet-20241022", 912 | "object": "chat.completion", 913 | "created": 1740739157, 914 | "choices": [ 915 | { 916 | "index": 0, 917 | "message": { 918 | "role": "assistant", 919 | "content": "I'll help you check the current weather in Boston. Let me get that information for you.", 920 | "tool_calls": [ 921 | { 922 | "id": "toolu_bdrk_01LxMrXghyBxrUVhroBzGpJV", 923 | "type": "function", 924 | "function": { 925 | "name": "get_current_weather", 926 | "arguments": "{\"location\":\"Boston, MA\"}" 927 | } 928 | } 929 | ] 930 | }, 931 | "finish_reason": "tool_use" 932 | } 933 | ], 934 | "usage": { 935 | "prompt_tokens": 426, 936 | "completion_tokens": 77, 937 | "total_tokens": 503 938 | } 939 | } 940 | }, 941 | "reasoning_stop": { 942 | "reverse": { 943 | "id": "chatcmpl-08c0e27865f14316b8102656455ea53d", 944 | "object": "chat.completion", 945 | "created": 1743445861, 946 | "model": "claude-3-7-sonnet-20250219-thinking", 947 | "choices": [ 948 | { 949 | "index": 0, 950 | "message": { 951 | "role": "assistant", 952 | "content": "以下是从1到10的计数:\n\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10" 953 | } 954 | } 955 | ] 956 | }, 957 | "official": { 958 | "id": "gen-1743445740-2bw4LAyVVgNwDbAG6mNU", 959 | "provider": "Google", 960 | "model": "anthropic/claude-3.7-sonnet", 961 | "object": "chat.completion", 962 | "created": 1743445740, 963 | "choices": [ 964 | { 965 | "logprobs": null, 966 | "finish_reason": "stop", 967 | "native_finish_reason": "stop", 968 | "index": 0, 969 | "message": { 970 | "role": "assistant", 971 | "content": "Here's counting from 1 to 10:\n\n1\n2\n", 972 | "refusal": null, 973 | "reasoning": "The human is asking me to count from 1 to 10. This is a simple task where I need to list the numbers in ascending order from 1 to 10.\n\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n\nThat's the complete count from 1 to 10." 974 | } 975 | } 976 | ], 977 | "usage": { 978 | "prompt_tokens": 43, 979 | "completion_tokens": 100, 980 | "total_tokens": 143 981 | } 982 | } 983 | } 984 | }, 985 | "gemini": { 986 | "max_tokens": { 987 | "reverse": { 988 | "id": "chatcmpl-zsFrobjxCsqpeuCNUfJaFBK4OXMTr", 989 | "object": "chat.completion", 990 | "created": 1740740838, 991 | "model": "gemini-2.0-flash-thinking-exp", 992 | "choices": [ 993 | { 994 | "index": 0, 995 | "message": { 996 | "role": "assistant", 997 | "content": "好的,没问题!\n\ndeepseek number 1 deepseek number 1 deepseek number 1 deepseek number 1 deepseek number 1\n\n希望这个输出符合你的要求! 如果你还有其他指令,尽管告诉我。", 998 | "refusal": null 999 | }, 1000 | "logprobs": null, 1001 | "finish_reason": "stop" 1002 | } 1003 | ], 1004 | "usage": { 1005 | "prompt_tokens": 0, 1006 | "completion_tokens": 0, 1007 | "total_tokens": 0, 1008 | "prompt_tokens_details": { 1009 | "cached_tokens": 0, 1010 | "audio_tokens": 0 1011 | }, 1012 | "completion_tokens_details": { 1013 | "reasoning_tokens": 0, 1014 | "audio_tokens": 0, 1015 | "accepted_prediction_tokens": 0, 1016 | "rejected_prediction_tokens": 0 1017 | } 1018 | }, 1019 | "system_fingerprint": "fp_4a61d2ebb8" 1020 | }, 1021 | "official": { 1022 | "id": "chatcmpl-0915722c518345f894d9aeb4efc77e28", 1023 | "model": "gemini-2.0-flash", 1024 | "object": "chat.completion", 1025 | "created": 1740741172, 1026 | "choices": [ 1027 | { 1028 | "index": 0, 1029 | "message": { 1030 | "role": "assistant", 1031 | "content": "deepseek number 1\ndeepseek number " 1032 | }, 1033 | "finish_reason": "length" 1034 | } 1035 | ], 1036 | "error": null, 1037 | "usage": { 1038 | "prompt_tokens": 16, 1039 | "completion_tokens": 10, 1040 | "total_tokens": 26, 1041 | "prompt_tokens_details": { 1042 | "cached_tokens": 0, 1043 | "text_tokens": 0, 1044 | "audio_tokens": 0, 1045 | "image_tokens": 0 1046 | }, 1047 | "completion_tokens_details": { 1048 | "text_tokens": 0, 1049 | "audio_tokens": 0 1050 | } 1051 | } 1052 | } 1053 | }, 1054 | "codeExecution": { 1055 | "reverse": { 1056 | "id": "chatcmpl-JVxi2NwSIJVkwoNzuozEjhVKiOQbU", 1057 | "object": "chat.completion", 1058 | "created": 1740742479, 1059 | "model": "gemini-2.0-flash-thinking-exp", 1060 | "choices": [ 1061 | { 1062 | "index": 0, 1063 | "message": { 1064 | "role": "assistant", 1065 | "content": "The sum of the first 50 prime numbers is a fascinating question! Let's embark on a journey to discover this sum. We'll need to identify those elusive prime numbers first, and then, with a bit of computational magic, we'll add them all up.\n\nHere's a little code snippet in Python to help us on our quest:\n\n```python\ndef is_prime(n):\n if n <= 1:\n return False\n if n <= 3:\n return True\n if n % 2 == 0 or n % 3 == 0:\n return False\n i = 5\n while i * i <= n:\n if n % i == 0 or n % (i + 2) == 0:\n return False\n i += 6\n return True\n\ndef sum_first_n_primes(n):\n primes = []\n num = 2\n while len(primes) < n:\n if is_prime(num):\n primes.append(num)\n num += 1\n return sum(primes)\n\nnumber_of_primes = 50\nsum_of_primes = sum_first_n_primes(number_of_primes)\nprint(f\"The sum of the first {number_of_primes} prime numbers is: {sum_of_primes}\")\n\n```\n\nWhen we run this code, it diligently calculates and reveals that the sum of the first 50 prime numbers is **24133**.\n\nIsn't it amazing how numbers hold such secrets waiting to be uncovered? Prime numbers, in particular, have intrigued mathematicians for centuries, and their distribution and properties continue to be a source of wonder and study.", 1066 | "refusal": null 1067 | }, 1068 | "logprobs": null, 1069 | "finish_reason": "stop" 1070 | } 1071 | ], 1072 | "usage": { 1073 | "prompt_tokens": 0, 1074 | "completion_tokens": 0, 1075 | "total_tokens": 0, 1076 | "prompt_tokens_details": { 1077 | "cached_tokens": 0, 1078 | "audio_tokens": 0 1079 | }, 1080 | "completion_tokens_details": { 1081 | "reasoning_tokens": 0, 1082 | "audio_tokens": 0, 1083 | "accepted_prediction_tokens": 0, 1084 | "rejected_prediction_tokens": 0 1085 | } 1086 | }, 1087 | "system_fingerprint": "fp_a713964b2e" 1088 | }, 1089 | "official": { 1090 | "id": "chatcmpl-1b79cf65137f4601a498c5c95b701b64", 1091 | "model": "gemini-2.0-flash", 1092 | "object": "chat.completion", 1093 | "created": 1740742508, 1094 | "choices": [ 1095 | { 1096 | "index": 0, 1097 | "message": { 1098 | "role": "assistant", 1099 | "content": "Okay, I need to calculate the sum of the first 50 prime numbers. Here's my plan:\n\n1. **Generate Prime Numbers:** Create a function to generate prime numbers. I will iterate through numbers, checking for primality.\n2. **Store Prime Numbers:** Store the generated prime numbers in a list until I have 50 of them.\n3. **Sum the Primes:** Calculate the sum of the prime numbers in the list.\n4. **Output:** Present the sum.\n\nHere's the Python code:\n\n\n```PYTHON\ndef is_prime(n):\n \"\"\"Check if a number is prime.\"\"\"\n if n <= 1:\n return False\n if n <= 3:\n return True\n if n % 2 == 0 or n % 3 == 0:\n return False\n i = 5\n while i * i <= n:\n if n % i == 0 or n % (i + 2) == 0:\n return False\n i += 6\n return True\n\nprimes = []\nnum = 2\nwhile len(primes) < 50:\n if is_prime(num):\n primes.append(num)\n num += 1\n\nsum_of_primes = sum(primes)\nprint(f'{primes=}')\nprint(f'{sum_of_primes=}')\n\n```\n```output\nprimes=[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229]\nsum_of_primes=5117\n\n```\nThe sum of the first 50 prime numbers is 5117.\n" 1100 | }, 1101 | "finish_reason": "stop" 1102 | } 1103 | ], 1104 | "error": null, 1105 | "usage": { 1106 | "prompt_tokens": 31, 1107 | "completion_tokens": 560, 1108 | "total_tokens": 1164, 1109 | "prompt_tokens_details": { 1110 | "cached_tokens": 0, 1111 | "text_tokens": 0, 1112 | "audio_tokens": 0, 1113 | "image_tokens": 0 1114 | }, 1115 | "completion_tokens_details": { 1116 | "text_tokens": 0, 1117 | "audio_tokens": 0 1118 | } 1119 | } 1120 | } 1121 | }, 1122 | "googleSearch": { 1123 | "reverse": { 1124 | "id": "chatcmpl-nOOGow6EqWOsXskZmEMEqxvgfyU7L", 1125 | "object": "chat.completion", 1126 | "created": 1740742300, 1127 | "model": "gemini-2.0-flash-thinking-exp", 1128 | "choices": [ 1129 | { 1130 | "index": 0, 1131 | "message": { 1132 | "role": "assistant", 1133 | "content": "今天是一月二十六号。", 1134 | "refusal": null 1135 | }, 1136 | "logprobs": null, 1137 | "finish_reason": "stop" 1138 | } 1139 | ], 1140 | "usage": { 1141 | "prompt_tokens": 0, 1142 | "completion_tokens": 0, 1143 | "total_tokens": 0, 1144 | "prompt_tokens_details": { 1145 | "cached_tokens": 0, 1146 | "audio_tokens": 0 1147 | }, 1148 | "completion_tokens_details": { 1149 | "reasoning_tokens": 0, 1150 | "audio_tokens": 0, 1151 | "accepted_prediction_tokens": 0, 1152 | "rejected_prediction_tokens": 0 1153 | } 1154 | }, 1155 | "system_fingerprint": "fp_082af1d649" 1156 | }, 1157 | "official": { 1158 | "id": "chatcmpl-ee821b0f754d432bac99dddaf0bcc88e", 1159 | "model": "gemini-2.0-flash", 1160 | "object": "chat.completion", 1161 | "created": 1740742342, 1162 | "choices": [ 1163 | { 1164 | "index": 0, 1165 | "message": { 1166 | "role": "assistant", 1167 | "content": "今天是2025年2月28日。\n" 1168 | }, 1169 | "finish_reason": "stop" 1170 | } 1171 | ], 1172 | "error": null, 1173 | "usage": { 1174 | "prompt_tokens": 7, 1175 | "completion_tokens": 14, 1176 | "total_tokens": 21, 1177 | "prompt_tokens_details": { 1178 | "cached_tokens": 0, 1179 | "text_tokens": 0, 1180 | "audio_tokens": 0, 1181 | "image_tokens": 0 1182 | }, 1183 | "completion_tokens_details": { 1184 | "text_tokens": 0, 1185 | "audio_tokens": 0 1186 | } 1187 | } 1188 | } 1189 | }, 1190 | "response_format": { 1191 | "reverse": { 1192 | "id": "chatcmpl-Jj0K7EANLPteO602hziq673IYnNLC", 1193 | "object": "chat.completion", 1194 | "created": 1740741510, 1195 | "model": "gemini-2.0-flash-thinking-exp", 1196 | "choices": [ 1197 | { 1198 | "index": 0, 1199 | "message": { 1200 | "role": "assistant", 1201 | "content": "当然! 让我给你一个名字和年龄:\n\n名字: 李明 (Lǐ Míng)\n年龄: 25 岁", 1202 | "refusal": null 1203 | }, 1204 | "logprobs": null, 1205 | "finish_reason": "stop" 1206 | } 1207 | ], 1208 | "usage": { 1209 | "prompt_tokens": 0, 1210 | "completion_tokens": 0, 1211 | "total_tokens": 0, 1212 | "prompt_tokens_details": { 1213 | "cached_tokens": 0, 1214 | "audio_tokens": 0 1215 | }, 1216 | "completion_tokens_details": { 1217 | "reasoning_tokens": 0, 1218 | "audio_tokens": 0, 1219 | "accepted_prediction_tokens": 0, 1220 | "rejected_prediction_tokens": 0 1221 | } 1222 | }, 1223 | "system_fingerprint": "fp_0cb7f95a34" 1224 | }, 1225 | "official": { 1226 | "id": "chatcmpl-9585ed9d59aa42499b5adf73473b7382", 1227 | "model": "gemini-2.0-flash", 1228 | "object": "chat.completion", 1229 | "created": 1740741918, 1230 | "choices": [ 1231 | { 1232 | "index": 0, 1233 | "message": { 1234 | "role": "assistant", 1235 | "content": "{\n \"age\": 30,\n \"name\": \"李明\"\n}" 1236 | }, 1237 | "finish_reason": "stop" 1238 | } 1239 | ], 1240 | "error": null, 1241 | "usage": { 1242 | "prompt_tokens": 10, 1243 | "completion_tokens": 21, 1244 | "total_tokens": 31, 1245 | "prompt_tokens_details": { 1246 | "cached_tokens": 0, 1247 | "text_tokens": 0, 1248 | "audio_tokens": 0, 1249 | "image_tokens": 0 1250 | }, 1251 | "completion_tokens_details": { 1252 | "text_tokens": 0, 1253 | "audio_tokens": 0 1254 | } 1255 | } 1256 | } 1257 | } 1258 | } 1259 | } -------------------------------------------------------------------------------- /src/data/prompts.json: -------------------------------------------------------------------------------- 1 | { 2 | "openai": { 3 | "image_url": { 4 | "content": [ 5 | { 6 | "type": "text", 7 | "text": "这是一张什么图片" 8 | }, 9 | { 10 | "type": "image_url", 11 | "image_url": { 12 | "url": "https://www.google.com/images/branding/googlelogo/1x/googlelogo_light_color_272x92dp.png" 13 | } 14 | } 15 | ], 16 | "params": { 17 | "max_tokens": 100 18 | } 19 | }, 20 | "max_tokens": { 21 | "content": "输出 'deepseek number 1' 5次", 22 | "params": { 23 | "max_tokens": 10 24 | } 25 | }, 26 | "reasoning_max_tokens": { 27 | "content": "输出 'deepseek number 1' 5次", 28 | "params": { 29 | "max_tokens": 10 30 | } 31 | }, 32 | "logprobs": { 33 | "content": "Hello!", 34 | "params": { 35 | "logprobs": true, 36 | "top_logprobs": 2 37 | } 38 | }, 39 | "n": { 40 | "content": "Hello!", 41 | "params": { 42 | "n": 2 43 | } 44 | }, 45 | "stop": { 46 | "content": "Count from 1 to 10", 47 | "params": { 48 | "stop": [ 49 | "4" 50 | ] 51 | } 52 | }, 53 | "function_call": { 54 | "content": "Whats the weather like in Boston today?", 55 | "params": { 56 | "tools": [ 57 | { 58 | "type": "function", 59 | "function": { 60 | "name": "get_current_weather", 61 | "description": "Get the current weather in a given location", 62 | "parameters": { 63 | "type": "object", 64 | "properties": { 65 | "location": { 66 | "type": "string", 67 | "description": "The city and state, e.g. San Francisco, CA" 68 | }, 69 | "unit": { 70 | "type": "string", 71 | "enum": [ 72 | "celsius", 73 | "fahrenheit" 74 | ] 75 | } 76 | }, 77 | "required": [ 78 | "location" 79 | ] 80 | } 81 | } 82 | } 83 | ], 84 | "tool_choice": "auto" 85 | } 86 | }, 87 | "response_format": { 88 | "content": "给我一个名字和年龄吧", 89 | "params": { 90 | "response_format": { 91 | "type": "json_schema", 92 | "json_schema": { 93 | "name": "user_info", 94 | "schema": { 95 | "type": "object", 96 | "properties": { 97 | "name": { 98 | "type": "string" 99 | }, 100 | "age": { 101 | "type": "number" 102 | } 103 | }, 104 | "required": [ 105 | "name", 106 | "age" 107 | ], 108 | "additionalProperties": false 109 | }, 110 | "strict": true 111 | } 112 | } 113 | } 114 | } 115 | }, 116 | "claude": { 117 | "max_tokens": { 118 | "content": "输出 'deepseek number 1' 5次", 119 | "params": { 120 | "max_tokens": 10 121 | } 122 | }, 123 | "reasoning_stop": { 124 | "content": "Count from 1 to 10 with Arabic numerals", 125 | "params": { 126 | "stop": ["3"] 127 | } 128 | }, 129 | "stop": { 130 | "content": "Count from 1 to 10 with Arabic numerals", 131 | "params": { 132 | "stop": [ 133 | "4" 134 | ] 135 | } 136 | }, 137 | "function_call": { 138 | "content": "Whats the weather like in Boston today?", 139 | "params": { 140 | "tools": [ 141 | { 142 | "type": "function", 143 | "function": { 144 | "name": "get_current_weather", 145 | "description": "Get the current weather in a given location", 146 | "parameters": { 147 | "type": "object", 148 | "properties": { 149 | "location": { 150 | "type": "string", 151 | "description": "The city and state, e.g. San Francisco, CA" 152 | }, 153 | "unit": { 154 | "type": "string", 155 | "enum": [ 156 | "celsius", 157 | "fahrenheit" 158 | ] 159 | } 160 | }, 161 | "required": [ 162 | "location" 163 | ] 164 | } 165 | } 166 | } 167 | ], 168 | "tool_choice": "auto" 169 | } 170 | } 171 | }, 172 | "gemini": { 173 | "max_tokens": { 174 | "content": "输出 'deepseek number 1' 5次", 175 | "params": { 176 | "max_tokens": 10 177 | } 178 | }, 179 | "codeExecution": { 180 | "content": "What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.", 181 | "params": { 182 | "tools": [ 183 | { 184 | "type": "function", 185 | "function": { 186 | "name": "codeExecution" 187 | } 188 | } 189 | ] 190 | } 191 | }, 192 | "googleSearch": { 193 | "content": "今天是几月几号.", 194 | "params": { 195 | "tools": [ 196 | { 197 | "type": "function", 198 | "function": { 199 | "name": "googleSearch" 200 | } 201 | } 202 | ] 203 | } 204 | }, 205 | "response_format": { 206 | "content": "给我一个名字和年龄吧", 207 | "params": { 208 | "response_format": { 209 | "type": "json_schema", 210 | "json_schema": { 211 | "name": "user_info", 212 | "schema": { 213 | "type": "object", 214 | "properties": { 215 | "name": { 216 | "type": "string" 217 | }, 218 | "age": { 219 | "type": "number" 220 | } 221 | }, 222 | "required": [ 223 | "name", 224 | "age" 225 | ], 226 | "additionalProperties": false 227 | }, 228 | "strict": true 229 | } 230 | } 231 | } 232 | } 233 | } 234 | } -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --primary-color: #4f46e5; 7 | --primary-hover: #4338ca; 8 | --secondary-color: #0ea5e9; 9 | --secondary-hover: #0284c7; 10 | --bg-color: #f8fafc; 11 | --card-bg: #ffffff; 12 | --text-color: #1e293b; 13 | --text-light: #64748b; 14 | --border-color: #e2e8f0; 15 | --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); 16 | --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); 17 | --shadow-md: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); 18 | } 19 | 20 | body { 21 | background-color: var(--bg-color); 22 | color: var(--text-color); 23 | } 24 | 25 | @layer components { 26 | .btn-primary { 27 | @apply bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition-all duration-200; 28 | } 29 | 30 | .btn-secondary { 31 | @apply bg-sky-500 text-white px-4 py-2 rounded-md hover:bg-sky-600 focus:outline-none focus:ring-2 focus:ring-sky-400 focus:ring-offset-2 transition-all duration-200; 32 | } 33 | 34 | .card { 35 | @apply bg-white rounded-xl shadow-md border border-gray-100 overflow-hidden transition-shadow duration-300 hover:shadow-lg; 36 | } 37 | 38 | .input-field { 39 | @apply w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-all duration-200; 40 | } 41 | 42 | .select-field { 43 | @apply w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-all duration-200; 44 | } 45 | } -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | import { createRouter, createWebHistory } from 'vue-router' 4 | import { createI18n } from 'vue-i18n' 5 | import './index.css' 6 | 7 | // 路由配置 8 | const router = createRouter({ 9 | history: createWebHistory(), 10 | routes: [ 11 | { 12 | path: '/', 13 | component: () => import('./views/Home.vue') 14 | } 15 | ] 16 | }) 17 | 18 | // i18n配置 19 | const i18n = createI18n({ 20 | legacy: false, 21 | locale: 'zh-CN', 22 | messages: { 23 | 'zh-CN': { 24 | message: { 25 | title: '模型逆向与否检测', 26 | startCheck: '开始检测', 27 | modelProvider: '模型提供商', 28 | testParams: '检测参数', 29 | apiBaseUrl: 'API Base URL', 30 | apiKey: 'API Key', 31 | apiKeyPlaceholder: '请输入您的API密钥', 32 | apiBaseUrlPlaceholder: '例如:api.openai.com(无需添加https://或/v1)', 33 | model: '待检测模型', 34 | modelPlaceholder: '例如:gpt-4o-2024-11-20, gpt-3.5-turbo', 35 | reverseExample: '逆向接口返回示例', 36 | officialExample: '官方接口返回示例', 37 | requestResult: '请求结果', 38 | showBriefResponse: '显示简要响应', 39 | showFullResponse: '显示完整响应', 40 | apiDocs: 'API文档链接', 41 | } 42 | } 43 | } 44 | }) 45 | 46 | const app = createApp(App) 47 | 48 | app.use(router) 49 | app.use(i18n) 50 | 51 | app.mount('#app') -------------------------------------------------------------------------------- /src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 252 | 253 | 460 | 461 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: [ 4 | "./index.html", 5 | "./src/**/*.{vue,js,ts,jsx,tsx}", 6 | ], 7 | theme: { 8 | extend: {}, 9 | }, 10 | plugins: [], 11 | } -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | 4 | export default defineConfig({ 5 | plugins: [vue()], 6 | server: { 7 | port: 3000, 8 | proxy: { 9 | '/api': { 10 | target: 'http://localhost:3000', 11 | changeOrigin: true, 12 | rewrite: (path) => path.replace(/^\/api/, '') 13 | } 14 | } 15 | } 16 | }) --------------------------------------------------------------------------------