尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

基于Gemini API与GCP云函数构建低成本博客AI助手实战指南

基于Gemini API与GCP云函数构建低成本博客AI助手实战指南 这次我们来看一个非常实用的个人项目如何为你的博客搭建一个成本可控的AI聊天助手。核心思路是利用Google的Gemini大模型、Cloud Functions云函数和Firestore数据库将月成本控制在5到15美元。对于个人开发者或博主来说这是一个极具性价比的解决方案既能提升网站互动性又无需承担高昂的服务器和模型推理费用。这个方案最吸引人的地方在于它的“无服务器”架构和按需付费模式。你不需要维护一台24小时运行的服务器AI模型的调用、对话历史的存储都由云服务商托管你只需为实际使用的资源付费。本文将带你从零开始一步步实现这个系统涵盖环境配置、代码编写、服务部署和效果测试。无论你是想为个人博客增加一个智能问答模块还是想学习如何将大模型API与云服务结合这篇文章都提供了完整的实操路径。1. 核心能力速览在开始动手之前我们先快速了解这个方案的核心特性和能力边界。能力项说明核心架构前端博客页面 后端Cloud Functions云函数 数据库Firestore AI模型Gemini API主要功能为博客访客提供基于上下文可选RAG的AI对话支持多轮对话记录对话历史。成本模型按使用量付费预估每月 $5 - $15取决于对话量、Firestore读写次数和Gemini API调用量。技术栈Python (Cloud Functions), Google Cloud Platform (GCP), Gemini API, Firestore, 前端JavaScript。启动方式通过gcloudCLI 命令行部署云函数无需手动管理服务器。接口能力提供HTTP API接口前端通过Fetch或Axios调用返回流式或非流式响应。扩展性易于集成RAG检索增强生成将博客文章作为知识库提升回答准确性。适合场景个人博客、小型内容网站、需要低成本AI交互功能的项目原型。2. 适用场景与使用边界这个方案非常适合以下人群和场景个人博主/技术写作者希望为读者提供一个可以咨询文章细节、获取相关知识的智能入口。小型项目所有者需要一个轻量级、可扩展的AI客服或问答系统且对成本敏感。学习云原生和AI集成的开发者通过一个完整项目实践GCP云函数、Firestore和Gemini API的集成。使用边界与注意事项网络访问Gemini API的调用需要稳定的网络环境。前端与云函数的通信应通过HTTPS确保安全。内容安全AI生成的内容不可控必须在后端或前端对输出内容进行适当过滤和审查避免生成不当言论。数据隐私对话历史存储在Firestore中需在隐私政策中告知用户并考虑提供清除对话历史的选项。成本监控虽然成本低但仍需在GCP控制台设置预算提醒防止意外流量导致费用激增。功能限制云函数有执行超时时间默认9分钟和冷启动问题不适合需要长时间持续会话或极低延迟的场景。3. 环境准备与前置条件在编写代码之前你需要准备好以下环境和账户Google Cloud Platform (GCP) 账户需要一个GCP账号。新用户通常有免费试用额度。启用所需API在GCP控制台中为你项目启用以下APICloud Functions APICloud Build APIFirestore APIGemini API (可能显示为 “Generative Language API”)安装 Google Cloud SDK (gcloud)这是部署和管理云函数的主要工具。Windows/macOS/Linux访问Google Cloud SDK官网下载并安装。安装后在终端运行gcloud init登录并配置默认项目。Python 环境本地需要安装Python 3.9或更高版本。建议使用虚拟环境如venv。代码编辑器如 VS Code、PyCharm 等。Gemini API 密钥在Google AI Studio中创建API密钥。4. 项目结构与代码实现我们将创建一个简单的项目包含一个云函数后端和一个示例前端页面。4.1 项目目录结构my-blog-ai-chat/ ├── backend/ │ ├── main.py # 云函数入口点 │ ├── requirements.txt # Python依赖 │ └── .gcloudignore # 部署忽略文件 ├── frontend/ │ └── index.html # 示例博客聊天组件 └── README.md4.2 后端云函数 (backend/main.py)这个函数处理来自前端的聊天请求调用Gemini API并将对话历史保存到Firestore。import functions_framework import google.generativeai as genai from google.cloud import firestore import json import os # 配置 Gemini API GEMINI_API_KEY os.environ.get(GEMINI_API_KEY) genai.configure(api_keyGEMINI_API_KEY) model genai.GenerativeModel(gemini-1.5-flash) # 选用性价比高的Flash模型 # 初始化 Firestore 客户端 db firestore.Client() functions_framework.http def chat_with_gemini(request): HTTP Cloud Function. Args: request (flask.Request): The HTTP request object. Returns: The response text, or any set of values that can be turned into a Response object using make_response # 设置CORS头允许你的博客域名访问 headers { Access-Control-Allow-Origin: https://your-blog.com, # 替换为你的博客域名 Access-Control-Allow-Methods: POST, OPTIONS, Access-Control-Allow-Headers: Content-Type, } if request.method OPTIONS: # 对预检请求直接返回200 return (, 204, headers) # 获取请求数据 request_json request.get_json(silentTrue) if not request_json: return json.dumps({error: Invalid JSON}), 400, headers user_message request_json.get(message, ) session_id request_json.get(session_id, default_session) # 用于区分不同访客的会话 if not user_message: return json.dumps({error: Message is required}), 400, headers # 1. 从Firestore获取历史对话 session_ref db.collection(chat_sessions).document(session_id) session_doc session_ref.get() history [] if session_doc.exists: history session_doc.to_dict().get(history, []) # 构建Gemini所需的对话历史格式可选简单示例仅发送最新消息 # 更复杂的实现可以将整个history构建成context chat model.start_chat(historyhistory) if history else model # 2. 调用Gemini API生成回复 try: response chat.send_message(user_message, streamFalse) ai_response response.text except Exception as e: return json.dumps({error: fAI service error: {str(e)}}), 500, headers # 3. 将本轮对话保存到Firestore历史中 new_history_entry {role: user, parts: [user_message]} history.append(new_history_entry) new_history_entry {role: model, parts: [ai_response]} history.append(new_history_entry) # 限制历史记录长度防止Firestore文档过大 max_history_length 20 if len(history) max_history_length: history history[-max_history_length:] session_ref.set({history: history}) # 4. 返回AI回复给前端 return json.dumps({reply: ai_response}), 200, headers4.3 后端依赖 (backend/requirements.txt)functions-framework3.* google-cloud-firestore2.0.0 google-generativeai0.3.04.4 前端示例 (frontend/index.html)这是一个极简的HTML示例展示如何集成到你的博客侧边栏或页面底部。!DOCTYPE html html head title博客AI助手/title style #chat-container { position: fixed; bottom: 20px; right: 20px; width: 350px; border: 1px solid #ccc; border-radius: 10px; background: white; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } #chat-header { background: #4285f4; color: white; padding: 10px; border-radius: 10px 10px 0 0; font-weight: bold; } #chat-messages { height: 300px; overflow-y: auto; padding: 10px; } .message { margin-bottom: 10px; padding: 8px 12px; border-radius: 18px; max-width: 80%; } .user-message { background: #e3f2fd; margin-left: auto; } .bot-message { background: #f1f3f4; } #chat-input-container { display: flex; border-top: 1px solid #eee; padding: 10px; } #user-input { flex-grow: 1; padding: 10px; border: 1px solid #ddd; border-radius: 20px; margin-right: 10px; } #send-btn { padding: 10px 20px; background: #4285f4; color: white; border: none; border-radius: 20px; cursor: pointer; } /style /head body div idchat-container div idchat-header 博客AI助手/div div idchat-messages div classmessage bot-message你好我是本博客的AI助手可以为你解答关于文章内容的问题。/div /div div idchat-input-container input typetext iduser-input placeholder输入你的问题... button idsend-btn onclicksendMessage()发送/button /div /div script // 生成一个简单的会话ID实际应用中可以用更复杂的方式如用户ID时间戳 const sessionId user_ Math.random().toString(36).substr(2, 9); // 替换为你的云函数URL const CLOUD_FUNCTION_URL https://YOUR_REGION-YOUR_PROJECT.cloudfunctions.net/chat_with_gemini; function addMessage(text, isUser) { const messagesDiv document.getElementById(chat-messages); const msgDiv document.createElement(div); msgDiv.className message ${isUser ? user-message : bot-message}; msgDiv.textContent text; messagesDiv.appendChild(msgDiv); messagesDiv.scrollTop messagesDiv.scrollHeight; } async function sendMessage() { const input document.getElementById(user-input); const message input.value.trim(); if (!message) return; addMessage(message, true); input.value ; input.disabled true; document.getElementById(send-btn).disabled true; try { const response await fetch(CLOUD_FUNCTION_URL, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ message: message, session_id: sessionId }) }); const data await response.json(); if (response.ok) { addMessage(data.reply, false); } else { addMessage(出错: ${data.error}, false); } } catch (error) { addMessage(网络请求失败请检查连接。, false); console.error(Error:, error); } finally { input.disabled false; document.getElementById(send-btn).disabled false; input.focus(); } } // 按回车发送消息 document.getElementById(user-input).addEventListener(keypress, function(e) { if (e.key Enter) { sendMessage(); } }); /script /body /html5. 部署与配置5.1 设置环境变量在部署云函数前需要设置Gemini API密钥作为环境变量避免硬编码在代码中。# 在本地或Cloud Shell中设置环境变量部署时使用 export GEMINI_API_KEYYOUR_ACTUAL_GEMINI_API_KEY5.2 部署云函数到GCP进入backend目录使用gcloud命令部署。cd backend gcloud functions deploy chat_with_gemini \ --runtime python39 \ --trigger-http \ --allow-unauthenticated \ --set-env-vars GEMINI_API_KEY$GEMINI_API_KEY \ --regionus-central1 \ --memory256MB \ --timeout60s参数解释--trigger-http: 创建一个HTTP触发的函数。--allow-unauthenticated: 允许未经身份验证的访问仅用于测试生产环境应考虑安全措施。--set-env-vars: 传入环境变量。--memory和--timeout: 根据需求调整。对于Gemini对话256MB内存通常足够。--region: 选择离你用户群近的区域。部署成功后命令行会输出一个httpsTrigger.url这就是你的云函数访问地址。5.3 配置Firestore数据库在GCP控制台进入Firestore。选择“以原生模式创建数据库”。选择一个位置建议与云函数同一区域。创建完成后无需手动创建集合或文档。我们的代码会在第一次请求时自动创建chat_sessions集合。5.4 集成前端到博客将frontend/index.html中的CLOUD_FUNCTION_URL变量值替换为你部署后得到的真实URL。将聊天组件的HTML结构和CSS样式整合到你博客的模板文件中如侧边栏sidebar.html或页脚footer.html。将JavaScript逻辑复制到你的全局JS文件或相应位置。6. 功能测试与效果验证部署完成后需要进行全面测试。6.1 测试1直接调用云函数API使用curl或 Postman 测试后端是否正常工作。curl -X POST https://YOUR_REGION-YOUR_PROJECT.cloudfunctions.net/chat_with_gemini \ -H Content-Type: application/json \ -d {message: 你好请介绍一下你自己, session_id: test_session_123}预期输出一个JSON对象包含{reply: ...}字段内容是Gemini生成的自我介绍。失败排查403 或 404 错误检查函数URL是否正确以及是否允许未授权访问。500 内部错误查看GCP Cloud Functions的日志。最常见的原因是GEMINI_API_KEY环境变量未正确设置或Gemini API未在项目中启用。6.2 测试2前端界面交互在浏览器中打开你的博客页面。找到并点击AI聊天助手图标或按钮打开聊天窗口。输入一个问题如“你基于什么技术搭建的”观察是否能收到连贯、相关的回复。进行多轮对话测试上下文是否保持。6.3 测试3验证Firestore数据持久化在GCP控制台进入Firestore。查看数据。你应该能看到一个名为chat_sessions的集合。点击进入一个文档文档ID即session_id查看其history字段应该是一个数组包含了用户和AI的对话记录。这证明了对话历史被成功存储。6.4 测试4成本监控验证在GCP控制台进入“结算”-“预算和提醒”。创建一个预算比如设置每月15美元。设置当预测费用达到预算的50%、90%和100%时发送邮件提醒。进行一些对话测试后进入“结算”-“报表”筛选到Cloud Functions和Firestore服务观察产生的微小费用。这能让你确信成本监控机制已生效。7. 进阶集成RAG检索增强生成基础版聊天机器人仅依赖Gemini的通用知识。要让它真正“懂”你的博客需要集成RAG使其能基于你的文章内容回答问题。7.1 核心思路知识库构建将你的博客文章Markdown/HTML进行文本提取、分块chunking。向量化与存储使用文本嵌入模型如Gemini Embedding API将文本块转换为向量存入支持向量搜索的数据库如Firestore的Vector Search或Chroma、Pinecone等。检索与生成当用户提问时将问题向量化从向量库中检索最相关的几个文本块将它们作为上下文Context连同问题一起发送给Gemini生成最终答案。7.2 实现步骤简述创建文章向量库编写一个离线脚本处理你的所有博文调用Gemini Embedding API生成向量并存储到Firestore的一个新集合如article_chunks中每个文档包含text原文块、embedding向量数组和source文章URL字段。修改云函数在函数中集成向量检索逻辑。当收到用户问题时先对问题生成嵌入向量。使用Firestore的向量相似度查询需预先创建向量索引或客户端计算余弦相似度检索出最相关的K个文本块。将检索到的文本块作为上下文与用户问题一起构造一个更详细的Prompt例如“请根据以下上下文回答问题{context} \n\n 问题{question}”再发送给Gemini。更新前端前端无需改动。注意集成RAG后每次调用会涉及一次Embedding API调用和一次Generative API调用成本会略有上升同时需要管理向量索引复杂度增加。但对于博客问答的准确性提升是显著的。8. 资源占用、性能与成本观察8.1 资源占用云函数侧内存我们设置了256MB。对于纯文本对话这绰绰有余。如果集成RAG检索过程可能消耗更多内存建议升级到512MB或1GB。执行时间Gemini API调用通常在2-10秒内返回。我们设置了60秒超时足够安全。冷启动云函数在闲置一段时间后再次调用会有“冷启动”延迟初始化环境。可以通过设置最小实例数有成本或定时发送“保温”请求来缓解。8.2 成本估算与监控成本主要来自三部分Cloud Functions按调用次数、计算时间和出站网络流量计费。前200万次调用/月免费之后每百万次约$0.40。我们的轻量级函数每月数千次调用成本几乎可忽略。Firestore按文档读写、删除操作和存储空间计费。每天免费5万次读取、2万次写入、2万次删除。存储免费额度为1GB。对于个人博客聊天很难超过免费额度。Gemini API这是主要成本来源。以gemini-1.5-flash为例价格可能变动请以官方为准输入每百万tokens约$0.075输出每百万tokens约$0.30一次典型的问答用户输入100字AI回复300字约合400 tokens成本约为(0.1*0.075 0.3*0.30)/1000 $0.0000975即约万分之一美元。估算如果每月有1000次对话总成本约$0.1。即使达到1万次也仅约$1。加上云函数和Firestore的微量费用总成本完全可以控制在$5-$15/月的范围内除非你的博客流量巨大。关键建议务必在GCP控制台设置预算提醒并定期查看“结算报表”了解费用构成。9. 常见问题与排查方法问题现象可能原因排查方式解决方案部署失败提示权限错误当前gcloud账号无权限或未设置项目。运行gcloud config list查看当前项目。运行gcloud auth list查看当前账号。使用gcloud config set project PROJECT_ID设置项目。使用gcloud auth login重新登录。云函数返回500错误1. 环境变量未设置。2. Gemini API未启用。3. 代码语法错误。在GCP控制台进入Cloud Functions - 点击函数名 - 查看“日志”标签页。1. 检查环境变量配置。2. 在GCP控制台启用Generative Language API。3. 根据日志错误信息修正代码。前端无法收到回复网络错误1. CORS配置错误。2. 云函数URL错误。3. 博客HTTPS函数HTTP混合内容错误。浏览器开发者工具 - 网络(Network)标签查看请求状态和响应头。1. 检查云函数代码中的CORS头确保允许你的博客域名。2. 核对前端JS中的函数URL。3. 确保云函数使用HTTPS URL。对话没有上下文每次都是新对话session_id未正确传递或处理。检查前端发送的session_id是否稳定如用本地存储。检查Firestore中是否生成了对应文档。确保同一用户会话使用相同的session_id。前端可以用localStorage存储一个生成的ID。响应速度慢1. 云函数冷启动。2. Gemini API响应慢。3. 网络延迟。查看云函数日志中的“执行时间”。连续发送第二次请求对比速度。1. 可考虑设置云函数最小实例数为1增加成本。2. 选择gemini-1.5-flash模型已是最快之一。3. 将云函数部署在离你用户近的区域。费用超出预期1. 被恶意刷接口。2. 前端有bug导致循环调用。3. RAG集成后调用量翻倍。查看结算报表分析是哪个服务Gemini/Function/Firestore费用高。查看云函数和Firestore的监控指标调用次数。1. 为云函数添加身份验证或API密钥验证。2. 修复前端bug。3. 优化RAG检索逻辑缓存嵌入向量。10. 最佳实践与使用建议安全第一生产环境务必移除--allow-unauthenticated改为使用IAM进行身份验证或为你的云函数配置一个API网关并设置API密钥。在前端或后端对用户输入和AI输出进行内容安全过滤防止生成有害信息。定期审计Firestore中的对话数据清理过期会话。成本优化使用gemini-1.5-flash而非gemini-1.5-pro它在保持良好性能的同时成本更低。合理设置对话历史长度如本文的20轮避免Firestore文档无限增大。利用GCP的免费额度。体验提升在前端实现流式输出Streaming让AI的回答逐字显示体验更佳。这需要修改后端使用Gemini的streamTrue参数并返回流式HTTP响应。为聊天机器人设计一个清晰的系统指令System Instruction定义它的身份、能力和回答边界比如“你是一个专注于本博客技术内容的助手对于无关问题应礼貌拒绝”。添加一个“清除对话”按钮让用户可以手动重置会话历史。维护与监控在GCP控制台为Cloud Functions和Firestore设置监控图表关注调用量、错误率和延迟。订阅错误日志的告警以便及时发现问题。定期更新项目依赖requirements.txt中的库以获得安全补丁和新功能。为个人博客添加一个智能聊天助手不再是需要庞大团队和高昂预算才能实现的事情。通过组合Gemini API、Cloud Functions和Firestore这些现代化的云服务我们可以在极低的成本和运维负担下构建一个功能完整、可扩展的AI交互系统。这个项目的价值不仅在于最终的功能更在于它提供了一个清晰的范本展示了如何将大模型能力以“无服务器”、按需付费的方式产品化。建议你先从基础版开始部署和测试确保整个链路跑通成本可控。然后再根据你的需求逐步考虑集成RAG、优化前端体验、增强安全措施等进阶功能。最重要的是立即在GCP控制台设置好预算提醒这样你就可以安心地进行各种实验和迭代了。
返回列表