From e6c272a529662f306d248d33e3f78d183f28de25 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 1 Sep 2025 10:15:05 +0000 Subject: [PATCH 1/2] Add Gemini API frontend and deployment documentation files Co-authored-by: sorrust --- DEPLOYMENT_CHECKLIST.md | 166 +++++++++++ GEMINI_FRONTEND_GUIDE.md | 317 +++++++++++++++++++++ gemini-client.js | 289 +++++++++++++++++++ gemini-frontend-example.html | 533 +++++++++++++++++++++++++++++++++++ gemini-node-example.js | 186 ++++++++++++ gemini-usage-example.html | 261 +++++++++++++++++ test-gemini-api.js | 270 ++++++++++++++++++ 7 files changed, 2022 insertions(+) create mode 100644 DEPLOYMENT_CHECKLIST.md create mode 100644 GEMINI_FRONTEND_GUIDE.md create mode 100644 gemini-client.js create mode 100644 gemini-frontend-example.html create mode 100644 gemini-node-example.js create mode 100644 gemini-usage-example.html create mode 100644 test-gemini-api.js diff --git a/DEPLOYMENT_CHECKLIST.md b/DEPLOYMENT_CHECKLIST.md new file mode 100644 index 0000000..e837bf4 --- /dev/null +++ b/DEPLOYMENT_CHECKLIST.md @@ -0,0 +1,166 @@ +# Gemini API 部署检查清单 + +## 🚀 服务器端配置 + +### 1. 环境变量设置 +- [ ] `GEMINI_API_KEY` - 已设置有效的 Gemini API 密钥 +- [ ] `NODE_ENV` - 设置为 `production`(生产环境) +- [ ] `CORS_ENABLED` - 设置为 `true`(如果需要跨域访问) + +### 2. 服务器配置 +- [ ] 服务器已启动并运行在正确的端口 +- [ ] 域名 `tko.tobenot.top` 已正确解析到服务器 IP +- [ ] SSL 证书已正确配置(HTTPS) +- [ ] 防火墙允许相应端口的访问 + +### 3. 网络配置 +- [ ] 服务器可以访问 `https://generativelanguage.googleapis.com` +- [ ] 网络连接稳定,延迟合理 +- [ ] 没有代理或防火墙阻止 API 请求 + +## 🌐 前端配置 + +### 1. 基础设置 +- [ ] 使用正确的 API 基础 URL:`https://tko.tobenot.top` +- [ ] 客户端库 `gemini-client.js` 已正确引入 +- [ ] 错误处理机制已实现 + +### 2. CORS 配置 +- [ ] 前端域名在服务器的 CORS 允许列表中 +- [ ] 浏览器支持所需的 Web API +- [ ] 没有浏览器扩展阻止请求 + +### 3. 用户体验 +- [ ] 加载状态已实现 +- [ ] 错误信息友好且有用 +- [ ] 流式响应有适当的视觉反馈 + +## 🔧 测试检查 + +### 1. 基础功能测试 +- [ ] 服务器健康检查:`GET /health` +- [ ] 基本聊天功能:`POST /v1/chat/completions` +- [ ] 流式聊天功能:`POST /v1/chat/completions` (stream: true) + +### 2. 模型测试 +- [ ] `gemini-1.5-pro` 模型正常工作 +- [ ] `gemini-1.5-flash` 模型正常工作 +- [ ] `gemini-1.0-pro` 模型正常工作 + +### 3. 错误处理测试 +- [ ] 网络错误处理 +- [ ] 认证错误处理 +- [ ] 请求超时处理 +- [ ] 服务器错误处理 + +## 📊 性能检查 + +### 1. 响应时间 +- [ ] 基本请求响应时间 < 5 秒 +- [ ] 流式响应首字节时间 < 2 秒 +- [ ] 服务器健康检查响应时间 < 1 秒 + +### 2. 并发处理 +- [ ] 可以处理多个并发请求 +- [ ] 队列机制正常工作 +- [ ] 没有内存泄漏 + +### 3. 错误率 +- [ ] 错误率 < 1% +- [ ] 超时率 < 0.1% +- [ ] 认证失败率 < 0.01% + +## 🔒 安全检查 + +### 1. 认证 +- [ ] API 密钥安全存储 +- [ ] 没有在客户端暴露敏感信息 +- [ ] 请求日志不包含敏感数据 + +### 2. 访问控制 +- [ ] CORS 配置正确 +- [ ] 没有不必要的开放端口 +- [ ] 防火墙规则正确 + +### 3. 数据保护 +- [ ] 用户数据不泄露 +- [ ] 请求内容不记录到日志 +- [ ] 适当的日志轮转 + +## 📈 监控检查 + +### 1. 服务器监控 +- [ ] CPU 使用率监控 +- [ ] 内存使用率监控 +- [ ] 网络流量监控 +- [ ] 错误率监控 + +### 2. 应用监控 +- [ ] API 响应时间监控 +- [ ] 请求成功率监控 +- [ ] 队列状态监控 +- [ ] 模型使用情况监控 + +### 3. 告警设置 +- [ ] 服务器宕机告警 +- [ ] 错误率过高告警 +- [ ] 响应时间过长告警 +- [ ] API 密钥失效告警 + +## 🚨 故障恢复 + +### 1. 备份策略 +- [ ] 服务器配置备份 +- [ ] 环境变量备份 +- [ ] SSL 证书备份 + +### 2. 恢复流程 +- [ ] 服务器重启流程 +- [ ] 配置恢复流程 +- [ ] 数据恢复流程 + +### 3. 应急响应 +- [ ] 联系信息更新 +- [ ] 故障升级流程 +- [ ] 用户通知机制 + +## 📝 文档检查 + +### 1. 技术文档 +- [ ] API 文档完整 +- [ ] 部署文档完整 +- [ ] 故障排除文档完整 + +### 2. 用户文档 +- [ ] 使用指南清晰 +- [ ] 示例代码完整 +- [ ] 常见问题解答 + +### 3. 运维文档 +- [ ] 监控指南 +- [ ] 故障处理流程 +- [ ] 维护计划 + +## ✅ 最终检查 + +### 部署前 +- [ ] 所有测试通过 +- [ ] 性能指标达标 +- [ ] 安全检查通过 +- [ ] 文档完整 + +### 部署后 +- [ ] 功能验证通过 +- [ ] 监控正常 +- [ ] 用户反馈良好 +- [ ] 性能稳定 + +### 持续维护 +- [ ] 定期检查清单 +- [ ] 性能优化 +- [ ] 安全更新 +- [ ] 功能扩展 + +--- + +**注意**: 这个检查清单应该根据具体项目需求进行调整。建议在每次部署前都进行完整的检查。 \ No newline at end of file diff --git a/GEMINI_FRONTEND_GUIDE.md b/GEMINI_FRONTEND_GUIDE.md new file mode 100644 index 0000000..f5f4032 --- /dev/null +++ b/GEMINI_FRONTEND_GUIDE.md @@ -0,0 +1,317 @@ +# Gemini API 前端使用指南 + +这个项目提供了使用部署在 `tko.tobenot.top` 的 Gemini API 的完整前端解决方案。 + +## 📁 文件说明 + +- `gemini-frontend-example.html` - 完整的 Gemini API 前端示例页面 +- `gemini-client.js` - JavaScript 客户端库 +- `gemini-usage-example.html` - 使用示例和测试页面 +- `gemini-node-example.js` - Node.js 环境使用示例 +- `test-gemini-api.js` - API 连接测试脚本 + +## 🚀 快速开始 + +### 1. 基本使用 + +```html + + + + Gemini API 示例 + + + + + + + + +``` + +### 2. 流式响应 + +```javascript +// 流式发送消息 +await client.sendMessageStream('请写一首诗', (chunk, fullContent) => { + console.log('收到数据块:', chunk); + console.log('完整内容:', fullContent); +}); +``` + +### 3. 对话会话 + +```javascript +// 创建对话会话 +const conversation = client.createConversation(); + +// 添加系统消息 +conversation.addSystemMessage('你是一个友好的助手,请用中文回答。'); + +// 发送消息并保持对话历史 +const reply1 = await conversation.sendMessage('你好!'); +const reply2 = await conversation.sendMessage('我刚才说了什么?'); +``` + +## 🔧 API 配置 + +### 支持的模型 + +- `gemini-1.5-pro` (推荐) +- `gemini-1.5-flash` (快速) +- `gemini-1.0-pro` + +### 客户端选项 + +```javascript +const client = new GeminiClient({ + baseUrl: 'https://tko.tobenot.top', // API 基础 URL + defaultModel: 'gemini-1.5-pro', // 默认模型 + defaultTemperature: 0.7, // 默认温度 (0.0-1.0) + defaultMaxTokens: 2000 // 默认最大令牌数 +}); +``` + +### 请求参数 + +```javascript +const response = await client.chat({ + messages: [ + { role: 'user', content: '你好!' } + ], + model: 'gemini-1.5-pro', // 可选,默认使用客户端设置 + temperature: 0.7, // 可选,控制创造性 + maxTokens: 2000, // 可选,最大输出长度 + stream: false // 可选,是否使用流式响应 +}); +``` + +## 📝 消息格式 + +### 消息对象结构 + +```javascript +{ + role: 'user' | 'assistant' | 'system', // 消息角色 + content: '消息内容' // 消息内容 +} +``` + +### 示例对话 + +```javascript +const messages = [ + { role: 'system', content: '你是一个有用的助手。' }, + { role: 'user', content: '你好!' }, + { role: 'assistant', content: '你好!有什么我可以帮助你的吗?' }, + { role: 'user', content: '请介绍一下你自己。' } +]; +``` + +## 🔄 流式响应处理 + +### 基本流式请求 + +```javascript +await client.sendMessageStream('请写一首诗', (chunk, fullContent) => { + // chunk: 当前数据块 + // fullContent: 到目前为止的完整内容 + console.log('收到:', chunk); + console.log('完整内容:', fullContent); +}); +``` + +### 在网页中显示流式响应 + +```javascript +const outputDiv = document.getElementById('output'); + +await client.sendMessageStream('请写一首诗', (chunk, fullContent) => { + outputDiv.textContent = fullContent; +}); +``` + +## 💬 对话会话管理 + +### 创建会话 + +```javascript +const conversation = client.createConversation(); +``` + +### 添加消息 + +```javascript +conversation.addSystemMessage('你是一个友好的助手。'); +conversation.addUserMessage('你好!'); +conversation.addAssistantMessage('你好!有什么可以帮助你的吗?'); +``` + +### 发送消息 + +```javascript +const reply = await conversation.sendMessage('请介绍一下你自己。'); +console.log(reply); +``` + +### 流式发送消息 + +```javascript +await conversation.sendMessageStream('请写一首诗', (chunk, fullContent) => { + console.log('收到:', chunk); +}); +``` + +### 管理对话历史 + +```javascript +// 获取所有消息 +const messages = conversation.getMessages(); + +// 清空对话历史 +conversation.clear(); +``` + +## 🛠️ 错误处理 + +### 基本错误处理 + +```javascript +try { + const response = await client.sendMessage('你好!'); + console.log(response); +} catch (error) { + console.error('请求失败:', error.message); + + if (error.message.includes('HTTP 401')) { + console.error('认证失败,请检查 API 密钥'); + } else if (error.message.includes('HTTP 429')) { + console.error('请求过于频繁,请稍后再试'); + } else if (error.message.includes('HTTP 500')) { + console.error('服务器内部错误'); + } else if (error.message.includes('fetch failed')) { + console.error('网络连接失败,请检查网络连接和域名解析'); + } +} +``` + +### 网络错误处理 + +```javascript +try { + const response = await client.sendMessage('你好!'); + console.log(response); +} catch (error) { + if (error.name === 'TypeError' && error.message.includes('fetch')) { + console.error('网络连接失败,请检查网络连接'); + } else { + console.error('未知错误:', error); + } +} +``` + +## 🌐 CORS 配置 + +如果你的前端应用运行在不同的域名下,确保服务器已正确配置 CORS。服务器支持以下域名: + +- `https://tko.tobenot.top` +- `https://tobenot.top` +- `http://localhost:5173` (开发环境) +- `http://127.0.0.1:5173` (开发环境) + +## 🔐 认证 + +服务器需要设置 `GEMINI_API_KEY` 环境变量来访问 Gemini API。前端不需要提供 API 密钥,所有认证都在服务器端处理。 + +## 📱 浏览器兼容性 + +- Chrome 88+ +- Firefox 85+ +- Safari 14+ +- Edge 88+ + +需要支持以下 Web API: +- `fetch()` +- `ReadableStream` +- `TextDecoder` +- `AbortController` + +## 🚨 注意事项 + +1. **请求频率限制**: 避免过于频繁的请求,建议在请求之间添加适当的延迟。 + +2. **错误处理**: 始终使用 try-catch 包装 API 调用。 + +3. **流式响应**: 流式响应需要正确处理数据块,确保在连接关闭时释放资源。 + +4. **对话历史**: 长时间对话可能会消耗大量令牌,建议定期清理对话历史。 + +5. **网络连接**: 确保网络连接稳定,特别是在使用流式响应时。 + +6. **域名解析**: 如果遇到连接问题,请检查域名 `tko.tobenot.top` 是否可以正常解析。 + +## 🔧 故障排除 + +### 常见问题 + +1. **网络连接失败** + - 检查网络连接是否正常 + - 确认域名 `tko.tobenot.top` 可以正常解析 + - 尝试使用其他网络环境 + +2. **CORS 错误** + - 确认前端域名在服务器的 CORS 允许列表中 + - 检查浏览器控制台的错误信息 + +3. **认证失败** + - 确认服务器已正确设置 `GEMINI_API_KEY` 环境变量 + - 检查 API 密钥是否有效 + +4. **请求超时** + - 增加请求超时时间 + - 检查网络延迟 + +### 测试连接 + +使用提供的测试脚本检查 API 连接: + +```bash +# 在浏览器中打开测试页面 +open gemini-frontend-example.html + +# 或者运行 Node.js 测试脚本 +node test-gemini-api.js +``` + +## 📞 支持 + +如果遇到问题,请检查: + +1. 网络连接是否正常 +2. 服务器是否正常运行 (`https://tko.tobenot.top/health`) +3. 浏览器控制台是否有错误信息 +4. 请求参数是否正确 +5. 域名解析是否正常 + +## 📄 许可证 + +本项目遵循 ISC 许可证。 \ No newline at end of file diff --git a/gemini-client.js b/gemini-client.js new file mode 100644 index 0000000..253aed9 --- /dev/null +++ b/gemini-client.js @@ -0,0 +1,289 @@ +/** + * Gemini API 客户端库 + * 用于与部署在 tko.tobenot.top 的 Gemini API 进行交互 + */ +class GeminiClient { + constructor(options = {}) { + this.baseUrl = options.baseUrl || 'https://tko.tobenot.top'; + this.defaultModel = options.defaultModel || 'gemini-1.5-pro'; + this.defaultTemperature = options.defaultTemperature || 0.7; + this.defaultMaxTokens = options.defaultMaxTokens || 2000; + } + + /** + * 发送聊天完成请求 + * @param {Object} options - 请求选项 + * @param {string} options.messages - 消息数组 + * @param {string} [options.model] - 模型名称 + * @param {number} [options.temperature] - 温度参数 + * @param {number} [options.maxTokens] - 最大令牌数 + * @param {boolean} [options.stream] - 是否使用流式响应 + * @returns {Promise} 响应数据 + */ + async chat(options) { + const { + messages, + model = this.defaultModel, + temperature = this.defaultTemperature, + maxTokens = this.defaultMaxTokens, + stream = false + } = options; + + if (!messages || !Array.isArray(messages)) { + throw new Error('messages 参数是必需的,且必须是数组'); + } + + const requestBody = { + model, + messages, + temperature, + max_tokens: maxTokens, + stream + }; + + const response = await fetch(`${this.baseUrl}/v1/chat/completions`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(requestBody) + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error(`HTTP ${response.status}: ${errorText}`); + } + + if (stream) { + return response.body; + } else { + return await response.json(); + } + } + + /** + * 发送简单消息并获取回复 + * @param {string} message - 用户消息 + * @param {Object} options - 其他选项 + * @returns {Promise} AI 回复内容 + */ + async sendMessage(message, options = {}) { + const response = await this.chat({ + messages: [{ role: 'user', content: message }], + ...options + }); + + if (response.choices && response.choices.length > 0) { + return response.choices[0].message.content; + } else { + throw new Error('响应中没有找到内容'); + } + } + + /** + * 流式发送消息 + * @param {string} message - 用户消息 + * @param {Function} onChunk - 处理每个数据块的函数 + * @param {Object} options - 其他选项 + * @returns {Promise} + */ + async sendMessageStream(message, onChunk, options = {}) { + const stream = await this.chat({ + messages: [{ role: 'user', content: message }], + stream: true, + ...options + }); + + if (!stream) { + throw new Error('无法获取流式响应'); + } + + const reader = stream.getReader(); + const decoder = new TextDecoder(); + let fullContent = ''; + + try { + while (true) { + const { done, value } = await reader.read(); + + if (done) break; + + const chunk = decoder.decode(value, { stream: true }); + const lines = chunk.split('\n'); + + for (const line of lines) { + if (line.startsWith('data: ')) { + const data = line.slice(6); + if (data === '[DONE]') { + return; + } + + try { + const json = JSON.parse(data); + const content = json.choices?.[0]?.delta?.content; + if (content) { + fullContent += content; + onChunk(content, fullContent); + } + } catch (e) { + // 忽略解析错误 + } + } + } + } + } finally { + reader.releaseLock(); + } + } + + /** + * 创建对话会话 + * @param {Object} options - 会话选项 + * @returns {ConversationSession} 对话会话对象 + */ + createConversation(options = {}) { + return new ConversationSession(this, options); + } +} + +/** + * 对话会话类 + */ +class ConversationSession { + constructor(client, options = {}) { + this.client = client; + this.messages = []; + this.options = options; + } + + /** + * 添加用户消息 + * @param {string} content - 消息内容 + */ + addUserMessage(content) { + this.messages.push({ role: 'user', content }); + } + + /** + * 添加助手消息 + * @param {string} content - 消息内容 + */ + addAssistantMessage(content) { + this.messages.push({ role: 'assistant', content }); + } + + /** + * 添加系统消息 + * @param {string} content - 消息内容 + */ + addSystemMessage(content) { + this.messages.unshift({ role: 'system', content }); + } + + /** + * 发送消息并获取回复 + * @param {string} message - 用户消息 + * @param {Object} options - 其他选项 + * @returns {Promise} AI 回复内容 + */ + async sendMessage(message, options = {}) { + this.addUserMessage(message); + + const response = await this.client.chat({ + messages: this.messages, + ...options + }); + + if (response.choices && response.choices.length > 0) { + const content = response.choices[0].message.content; + this.addAssistantMessage(content); + return content; + } else { + throw new Error('响应中没有找到内容'); + } + } + + /** + * 流式发送消息 + * @param {string} message - 用户消息 + * @param {Function} onChunk - 处理每个数据块的函数 + * @param {Object} options - 其他选项 + * @returns {Promise} + */ + async sendMessageStream(message, onChunk, options = {}) { + this.addUserMessage(message); + + const stream = await this.client.chat({ + messages: this.messages, + stream: true, + ...options + }); + + if (!stream) { + throw new Error('无法获取流式响应'); + } + + const reader = stream.getReader(); + const decoder = new TextDecoder(); + let fullContent = ''; + + try { + while (true) { + const { done, value } = await reader.read(); + + if (done) break; + + const chunk = decoder.decode(value, { stream: true }); + const lines = chunk.split('\n'); + + for (const line of lines) { + if (line.startsWith('data: ')) { + const data = line.slice(6); + if (data === '[DONE]') { + this.addAssistantMessage(fullContent); + return; + } + + try { + const json = JSON.parse(data); + const content = json.choices?.[0]?.delta?.content; + if (content) { + fullContent += content; + onChunk(content, fullContent); + } + } catch (e) { + // 忽略解析错误 + } + } + } + } + } finally { + reader.releaseLock(); + } + } + + /** + * 清空对话历史 + */ + clear() { + this.messages = []; + } + + /** + * 获取对话历史 + * @returns {Array} 消息数组 + */ + getMessages() { + return [...this.messages]; + } +} + +// 导出类 +if (typeof module !== 'undefined' && module.exports) { + // Node.js 环境 + module.exports = { GeminiClient, ConversationSession }; +} else if (typeof window !== 'undefined') { + // 浏览器环境 + window.GeminiClient = GeminiClient; + window.ConversationSession = ConversationSession; +} \ No newline at end of file diff --git a/gemini-frontend-example.html b/gemini-frontend-example.html new file mode 100644 index 0000000..156f65e --- /dev/null +++ b/gemini-frontend-example.html @@ -0,0 +1,533 @@ + + + + + + Gemini API 前端示例 + + + +
+
+ +

Gemini API 前端示例

+

使用部署在 tko.tobenot.top 的 Gemini API

+
+ +
+

API 端点信息

+

基础 URL: https://tko.tobenot.top

+

聊天完成端点: /v1/chat/completions

+

支持的模型: gemini-1.5-pro, gemini-1.5-flash, gemini-1.0-pro

+

认证: 需要设置 GEMINI_API_KEY 环境变量

+
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + + +
+
+ +
+
+

正在处理请求...

+
+ +
+ + +
+ + + + \ No newline at end of file diff --git a/gemini-node-example.js b/gemini-node-example.js new file mode 100644 index 0000000..3ba26d5 --- /dev/null +++ b/gemini-node-example.js @@ -0,0 +1,186 @@ +/** + * Node.js 环境下的 Gemini API 使用示例 + * 需要先安装 node-fetch: npm install node-fetch + */ + +// 如果使用 Node.js 18+,可以直接使用内置的 fetch +// 如果使用较老版本,需要安装 node-fetch +// const fetch = require('node-fetch'); + +class GeminiClientNode { + constructor(options = {}) { + this.baseUrl = options.baseUrl || 'https://tko.tobenot.top'; + this.defaultModel = options.defaultModel || 'gemini-1.5-pro'; + this.defaultTemperature = options.defaultTemperature || 0.7; + this.defaultMaxTokens = options.defaultMaxTokens || 2000; + } + + /** + * 发送聊天完成请求 + */ + async chat(options) { + const { + messages, + model = this.defaultModel, + temperature = this.defaultTemperature, + maxTokens = this.defaultMaxTokens, + stream = false + } = options; + + if (!messages || !Array.isArray(messages)) { + throw new Error('messages 参数是必需的,且必须是数组'); + } + + const requestBody = { + model, + messages, + temperature, + max_tokens: maxTokens, + stream + }; + + const response = await fetch(`${this.baseUrl}/v1/chat/completions`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(requestBody) + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error(`HTTP ${response.status}: ${errorText}`); + } + + if (stream) { + return response.body; + } else { + return await response.json(); + } + } + + /** + * 发送简单消息并获取回复 + */ + async sendMessage(message, options = {}) { + const response = await this.chat({ + messages: [{ role: 'user', content: message }], + ...options + }); + + if (response.choices && response.choices.length > 0) { + return response.choices[0].message.content; + } else { + throw new Error('响应中没有找到内容'); + } + } + + /** + * 流式发送消息 + */ + async sendMessageStream(message, onChunk, options = {}) { + const stream = await this.chat({ + messages: [{ role: 'user', content: message }], + stream: true, + ...options + }); + + if (!stream) { + throw new Error('无法获取流式响应'); + } + + const reader = stream.getReader(); + const decoder = new TextDecoder(); + let fullContent = ''; + + try { + while (true) { + const { done, value } = await reader.read(); + + if (done) break; + + const chunk = decoder.decode(value, { stream: true }); + const lines = chunk.split('\n'); + + for (const line of lines) { + if (line.startsWith('data: ')) { + const data = line.slice(6); + if (data === '[DONE]') { + return; + } + + try { + const json = JSON.parse(data); + const content = json.choices?.[0]?.delta?.content; + if (content) { + fullContent += content; + onChunk(content, fullContent); + } + } catch (e) { + // 忽略解析错误 + } + } + } + } + } finally { + reader.releaseLock(); + } + } +} + +// 使用示例 +async function main() { + const client = new GeminiClientNode({ + baseUrl: 'https://tko.tobenot.top', + defaultModel: 'gemini-1.5-pro' + }); + + console.log('🤖 Gemini API Node.js 示例\n'); + + try { + // 1. 基本消息发送 + console.log('1. 发送基本消息...'); + const response = await client.sendMessage('你好!请简单介绍一下你自己。'); + console.log('AI 回复:', response); + console.log(''); + + // 2. 流式响应 + console.log('2. 流式响应示例...'); + await client.sendMessageStream('请写一首关于春天的短诗', (chunk, fullContent) => { + process.stdout.write(chunk); + }); + console.log('\n'); + + // 3. 复杂对话 + console.log('3. 复杂对话示例...'); + const messages = [ + { role: 'system', content: '你是一个专业的编程助手,请用中文回答。' }, + { role: 'user', content: '请解释一下什么是 RESTful API?' } + ]; + + const complexResponse = await client.chat({ messages }); + console.log('AI 回复:', complexResponse.choices[0].message.content); + console.log(''); + + // 4. 不同模型的比较 + console.log('4. 不同模型的比较...'); + const models = ['gemini-1.5-pro', 'gemini-1.5-flash']; + + for (const model of models) { + console.log(`\n使用模型: ${model}`); + const modelResponse = await client.sendMessage('请用一句话介绍你自己', { model }); + console.log(`回复: ${modelResponse}`); + } + + } catch (error) { + console.error('❌ 错误:', error.message); + } +} + +// 如果直接运行此文件 +if (require.main === module) { + main().catch(console.error); +} + +// 导出类 +module.exports = { GeminiClientNode }; \ No newline at end of file diff --git a/gemini-usage-example.html b/gemini-usage-example.html new file mode 100644 index 0000000..5d7aa1c --- /dev/null +++ b/gemini-usage-example.html @@ -0,0 +1,261 @@ + + + + + + Gemini API 使用示例 + + + +

🤖 Gemini API 使用示例

+

这个页面展示了如何使用部署在 tko.tobenot.top 的 Gemini API。

+ + + + +
+

1. 基本使用

+
+// 创建客户端实例 +const client = new GeminiClient({ + baseUrl: 'https://tko.tobenot.top', + defaultModel: 'gemini-1.5-pro' +}); + +// 发送简单消息 +const response = await client.sendMessage('你好!'); +console.log(response); +
+ + +
+ +
+

2. 流式响应

+
+// 流式发送消息 +await client.sendMessageStream('请写一首关于春天的诗', (chunk, fullContent) => { + console.log('收到数据块:', chunk); + console.log('完整内容:', fullContent); +}); +
+ + +
+ +
+

3. 对话会话

+
+// 创建对话会话 +const conversation = client.createConversation(); + +// 添加系统消息 +conversation.addSystemMessage('你是一个友好的助手,请用中文回答。'); + +// 发送消息并保持对话历史 +const reply1 = await conversation.sendMessage('你好!'); +const reply2 = await conversation.sendMessage('我刚才说了什么?'); +
+ + +
+ +
+

4. 实时聊天界面

+
+
+
+ + + +
+
+
+ + + + \ No newline at end of file diff --git a/test-gemini-api.js b/test-gemini-api.js new file mode 100644 index 0000000..9023193 --- /dev/null +++ b/test-gemini-api.js @@ -0,0 +1,270 @@ +#!/usr/bin/env node + +/** + * Gemini API 连接测试脚本 + * 用于测试部署在 tko.tobenot.top 的 Gemini API 是否正常工作 + */ + +const API_BASE = 'https://tko.tobenot.top'; + +// 测试函数 +async function testHealth() { + console.log('🏥 测试服务器健康状态...'); + try { + const response = await fetch(`${API_BASE}/health`); + if (response.ok) { + const data = await response.json(); + console.log('✅ 服务器健康状态正常:', data); + return true; + } else { + console.log('❌ 服务器健康检查失败:', response.status); + return false; + } + } catch (error) { + console.log('❌ 无法连接到服务器:', error.message); + return false; + } +} + +async function testBasicChat() { + console.log('\n💬 测试基本聊天功能...'); + try { + const response = await fetch(`${API_BASE}/v1/chat/completions`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + model: 'gemini-1.5-pro', + messages: [ + { role: 'user', content: '你好!请简单回复"测试成功"。' } + ], + temperature: 0.7, + max_tokens: 100, + stream: false + }) + }); + + if (response.ok) { + const data = await response.json(); + console.log('✅ 基本聊天功能正常'); + console.log('AI 回复:', data.choices[0].message.content); + return true; + } else { + const errorText = await response.text(); + console.log('❌ 基本聊天功能失败:', response.status, errorText); + return false; + } + } catch (error) { + console.log('❌ 基本聊天功能错误:', error.message); + return false; + } +} + +async function testStreamingChat() { + console.log('\n🌊 测试流式聊天功能...'); + try { + const response = await fetch(`${API_BASE}/v1/chat/completions`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + model: 'gemini-1.5-pro', + messages: [ + { role: 'user', content: '请说"流式测试成功"' } + ], + temperature: 0.7, + max_tokens: 50, + stream: true + }) + }); + + if (response.ok && response.body) { + console.log('✅ 流式聊天功能正常'); + const reader = response.body.getReader(); + const decoder = new TextDecoder(); + let receivedData = false; + + try { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + + const chunk = decoder.decode(value, { stream: true }); + const lines = chunk.split('\n'); + + for (const line of lines) { + if (line.startsWith('data: ')) { + const data = line.slice(6); + if (data === '[DONE]') { + if (receivedData) { + console.log('✅ 流式数据接收完成'); + return true; + } + } else { + try { + const json = JSON.parse(data); + const content = json.choices?.[0]?.delta?.content; + if (content) { + process.stdout.write(content); + receivedData = true; + } + } catch (e) { + // 忽略解析错误 + } + } + } + } + } + } finally { + reader.releaseLock(); + } + return receivedData; + } else { + const errorText = await response.text(); + console.log('❌ 流式聊天功能失败:', response.status, errorText); + return false; + } + } catch (error) { + console.log('❌ 流式聊天功能错误:', error.message); + return false; + } +} + +async function testDifferentModels() { + console.log('\n🤖 测试不同模型...'); + const models = ['gemini-1.5-pro', 'gemini-1.5-flash', 'gemini-1.0-pro']; + const results = {}; + + for (const model of models) { + try { + console.log(`测试模型: ${model}`); + const response = await fetch(`${API_BASE}/v1/chat/completions`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + model: model, + messages: [ + { role: 'user', content: '请回复"OK"' } + ], + temperature: 0.1, + max_tokens: 10, + stream: false + }) + }); + + if (response.ok) { + const data = await response.json(); + results[model] = '✅ 正常'; + console.log(` ${model}: ✅ 正常`); + } else { + results[model] = '❌ 失败'; + console.log(` ${model}: ❌ 失败`); + } + } catch (error) { + results[model] = '❌ 错误'; + console.log(` ${model}: ❌ 错误 - ${error.message}`); + } + } + + return results; +} + +async function testCORS() { + console.log('\n🌐 测试 CORS 配置...'); + try { + const response = await fetch(`${API_BASE}/v1/chat/completions`, { + method: 'OPTIONS', + headers: { + 'Origin': 'https://example.com', + 'Access-Control-Request-Method': 'POST', + 'Access-Control-Request-Headers': 'Content-Type' + } + }); + + const corsHeaders = { + 'Access-Control-Allow-Origin': response.headers.get('Access-Control-Allow-Origin'), + 'Access-Control-Allow-Methods': response.headers.get('Access-Control-Allow-Methods'), + 'Access-Control-Allow-Headers': response.headers.get('Access-Control-Allow-Headers') + }; + + console.log('CORS 头信息:', corsHeaders); + + if (corsHeaders['Access-Control-Allow-Origin']) { + console.log('✅ CORS 配置正常'); + return true; + } else { + console.log('❌ CORS 配置可能有问题'); + return false; + } + } catch (error) { + console.log('❌ CORS 测试失败:', error.message); + return false; + } +} + +// 主测试函数 +async function runTests() { + console.log('🚀 开始 Gemini API 连接测试...\n'); + console.log(`目标服务器: ${API_BASE}\n`); + + const results = { + health: await testHealth(), + basicChat: await testBasicChat(), + streamingChat: await testStreamingChat(), + cors: await testCORS(), + models: await testDifferentModels() + }; + + // 输出测试结果摘要 + console.log('\n📊 测试结果摘要:'); + console.log('================'); + console.log(`服务器健康状态: ${results.health ? '✅ 正常' : '❌ 失败'}`); + console.log(`基本聊天功能: ${results.basicChat ? '✅ 正常' : '❌ 失败'}`); + console.log(`流式聊天功能: ${results.streamingChat ? '✅ 正常' : '❌ 失败'}`); + console.log(`CORS 配置: ${results.cors ? '✅ 正常' : '❌ 失败'}`); + console.log('\n模型支持情况:'); + Object.entries(results.models).forEach(([model, status]) => { + console.log(` ${model}: ${status}`); + }); + + // 总体评估 + const criticalTests = [results.health, results.basicChat]; + const allCriticalPassed = criticalTests.every(test => test === true); + + console.log('\n🎯 总体评估:'); + if (allCriticalPassed) { + console.log('✅ Gemini API 服务器运行正常,可以正常使用!'); + console.log('\n💡 使用建议:'); + console.log(' - 前端可以直接使用提供的 gemini-client.js 库'); + console.log(' - 支持流式响应和对话会话功能'); + console.log(' - 建议在生产环境中添加适当的错误处理和重试机制'); + } else { + console.log('❌ 关键功能测试失败,请检查服务器配置'); + console.log('\n🔧 故障排除建议:'); + console.log(' - 检查服务器是否正常运行'); + console.log(' - 确认 GEMINI_API_KEY 环境变量已正确设置'); + console.log(' - 检查网络连接和防火墙设置'); + console.log(' - 查看服务器日志以获取更多错误信息'); + } +} + +// 运行测试 +if (require.main === module) { + runTests().catch(error => { + console.error('❌ 测试过程中发生错误:', error); + process.exit(1); + }); +} + +module.exports = { + testHealth, + testBasicChat, + testStreamingChat, + testDifferentModels, + testCORS, + runTests +}; \ No newline at end of file From 2ad6969d42a062d2569608d084ec6b3d838c7e3f Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 1 Sep 2025 10:17:54 +0000 Subject: [PATCH 2/2] Update domain from tko to tyo in Gemini API frontend examples Co-authored-by: sorrust --- DEPLOYMENT_CHECKLIST.md | 4 +- GEMINI_FRONTEND_GUIDE.md | 14 +- GEMINI_INTEGRATION_SUMMARY.md | 95 ++++++ gemini-examples/README.md | 126 +++++++ .../gemini-client.js | 2 +- .../gemini-frontend-example.html | 6 +- .../gemini-node-example.js | 4 +- .../gemini-usage-example.html | 4 +- gemini-examples/quick-test.html | 320 ++++++++++++++++++ .../test-gemini-api.js | 2 +- 10 files changed, 559 insertions(+), 18 deletions(-) create mode 100644 GEMINI_INTEGRATION_SUMMARY.md create mode 100644 gemini-examples/README.md rename gemini-client.js => gemini-examples/gemini-client.js (99%) rename gemini-frontend-example.html => gemini-examples/gemini-frontend-example.html (98%) rename gemini-node-example.js => gemini-examples/gemini-node-example.js (98%) rename gemini-usage-example.html => gemini-examples/gemini-usage-example.html (98%) create mode 100644 gemini-examples/quick-test.html rename test-gemini-api.js => gemini-examples/test-gemini-api.js (99%) diff --git a/DEPLOYMENT_CHECKLIST.md b/DEPLOYMENT_CHECKLIST.md index e837bf4..6222870 100644 --- a/DEPLOYMENT_CHECKLIST.md +++ b/DEPLOYMENT_CHECKLIST.md @@ -9,7 +9,7 @@ ### 2. 服务器配置 - [ ] 服务器已启动并运行在正确的端口 -- [ ] 域名 `tko.tobenot.top` 已正确解析到服务器 IP +- [ ] 域名 `tyo.tobenot.top` 已正确解析到服务器 IP - [ ] SSL 证书已正确配置(HTTPS) - [ ] 防火墙允许相应端口的访问 @@ -21,7 +21,7 @@ ## 🌐 前端配置 ### 1. 基础设置 -- [ ] 使用正确的 API 基础 URL:`https://tko.tobenot.top` +- [ ] 使用正确的 API 基础 URL:`https://tyo.tobenot.top` - [ ] 客户端库 `gemini-client.js` 已正确引入 - [ ] 错误处理机制已实现 diff --git a/GEMINI_FRONTEND_GUIDE.md b/GEMINI_FRONTEND_GUIDE.md index f5f4032..3dd73a7 100644 --- a/GEMINI_FRONTEND_GUIDE.md +++ b/GEMINI_FRONTEND_GUIDE.md @@ -1,6 +1,6 @@ # Gemini API 前端使用指南 -这个项目提供了使用部署在 `tko.tobenot.top` 的 Gemini API 的完整前端解决方案。 +这个项目提供了使用部署在 `tyo.tobenot.top` 的 Gemini API 的完整前端解决方案。 ## 📁 文件说明 @@ -27,7 +27,7 @@ @@ -137,7 +137,7 @@

4. 实时聊天界面

+ + \ No newline at end of file diff --git a/test-gemini-api.js b/gemini-examples/test-gemini-api.js similarity index 99% rename from test-gemini-api.js rename to gemini-examples/test-gemini-api.js index 9023193..8d10e94 100644 --- a/test-gemini-api.js +++ b/gemini-examples/test-gemini-api.js @@ -5,7 +5,7 @@ * 用于测试部署在 tko.tobenot.top 的 Gemini API 是否正常工作 */ -const API_BASE = 'https://tko.tobenot.top'; +const API_BASE = 'https://tyo.tobenot.top'; // 测试函数 async function testHealth() {