[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"similar-google-gemini-php--laravel":3,"tool-google-gemini-php--laravel":64},[4,17,27,35,43,56],{"id":5,"name":6,"github_repo":7,"description_zh":8,"stars":9,"difficulty_score":10,"last_commit_at":11,"category_tags":12,"status":16},3808,"stable-diffusion-webui","AUTOMATIC1111\u002Fstable-diffusion-webui","stable-diffusion-webui 是一个基于 Gradio 构建的网页版操作界面，旨在让用户能够轻松地在本地运行和使用强大的 Stable Diffusion 图像生成模型。它解决了原始模型依赖命令行、操作门槛高且功能分散的痛点，将复杂的 AI 绘图流程整合进一个直观易用的图形化平台。\n\n无论是希望快速上手的普通创作者、需要精细控制画面细节的设计师，还是想要深入探索模型潜力的开发者与研究人员，都能从中获益。其核心亮点在于极高的功能丰富度：不仅支持文生图、图生图、局部重绘（Inpainting）和外绘（Outpainting）等基础模式，还独创了注意力机制调整、提示词矩阵、负向提示词以及“高清修复”等高级功能。此外，它内置了 GFPGAN 和 CodeFormer 等人脸修复工具，支持多种神经网络放大算法，并允许用户通过插件系统无限扩展能力。即使是显存有限的设备，stable-diffusion-webui 也提供了相应的优化选项，让高质量的 AI 艺术创作变得触手可及。",162132,3,"2026-04-05T11:01:52",[13,14,15],"开发框架","图像","Agent","ready",{"id":18,"name":19,"github_repo":20,"description_zh":21,"stars":22,"difficulty_score":23,"last_commit_at":24,"category_tags":25,"status":16},1381,"everything-claude-code","affaan-m\u002Feverything-claude-code","everything-claude-code 是一套专为 AI 编程助手（如 Claude Code、Codex、Cursor 等）打造的高性能优化系统。它不仅仅是一组配置文件，而是一个经过长期实战打磨的完整框架，旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。\n\n通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能，everything-claude-code 能显著提升 AI 在复杂任务中的表现，帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略，使得模型响应更快、成本更低，同时有效防御潜在的攻击向量。\n\n这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库，还是需要 AI 协助进行安全审计与自动化测试，everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目，它融合了多语言支持与丰富的实战钩子（hooks），让 AI 真正成长为懂上",138956,2,"2026-04-05T11:33:21",[13,15,26],"语言模型",{"id":28,"name":29,"github_repo":30,"description_zh":31,"stars":32,"difficulty_score":23,"last_commit_at":33,"category_tags":34,"status":16},2271,"ComfyUI","Comfy-Org\u002FComfyUI","ComfyUI 是一款功能强大且高度模块化的视觉 AI 引擎，专为设计和执行复杂的 Stable Diffusion 图像生成流程而打造。它摒弃了传统的代码编写模式，采用直观的节点式流程图界面，让用户通过连接不同的功能模块即可构建个性化的生成管线。\n\n这一设计巧妙解决了高级 AI 绘图工作流配置复杂、灵活性不足的痛点。用户无需具备编程背景，也能自由组合模型、调整参数并实时预览效果，轻松实现从基础文生图到多步骤高清修复等各类复杂任务。ComfyUI 拥有极佳的兼容性，不仅支持 Windows、macOS 和 Linux 全平台，还广泛适配 NVIDIA、AMD、Intel 及苹果 Silicon 等多种硬件架构，并率先支持 SDXL、Flux、SD3 等前沿模型。\n\n无论是希望深入探索算法潜力的研究人员和开发者，还是追求极致创作自由度的设计师与资深 AI 绘画爱好者，ComfyUI 都能提供强大的支持。其独特的模块化架构允许社区不断扩展新功能，使其成为当前最灵活、生态最丰富的开源扩散模型工具之一，帮助用户将创意高效转化为现实。",107662,"2026-04-03T11:11:01",[13,14,15],{"id":36,"name":37,"github_repo":38,"description_zh":39,"stars":40,"difficulty_score":23,"last_commit_at":41,"category_tags":42,"status":16},3704,"NextChat","ChatGPTNextWeb\u002FNextChat","NextChat 是一款轻量且极速的 AI 助手，旨在为用户提供流畅、跨平台的大模型交互体验。它完美解决了用户在多设备间切换时难以保持对话连续性，以及面对众多 AI 模型不知如何统一管理的痛点。无论是日常办公、学习辅助还是创意激发，NextChat 都能让用户随时随地通过网页、iOS、Android、Windows、MacOS 或 Linux 端无缝接入智能服务。\n\n这款工具非常适合普通用户、学生、职场人士以及需要私有化部署的企业团队使用。对于开发者而言，它也提供了便捷的自托管方案，支持一键部署到 Vercel 或 Zeabur 等平台。\n\nNextChat 的核心亮点在于其广泛的模型兼容性，原生支持 Claude、DeepSeek、GPT-4 及 Gemini Pro 等主流大模型，让用户在一个界面即可自由切换不同 AI 能力。此外，它还率先支持 MCP（Model Context Protocol）协议，增强了上下文处理能力。针对企业用户，NextChat 提供专业版解决方案，具备品牌定制、细粒度权限控制、内部知识库整合及安全审计等功能，满足公司对数据隐私和个性化管理的高标准要求。",87618,"2026-04-05T07:20:52",[13,26],{"id":44,"name":45,"github_repo":46,"description_zh":47,"stars":48,"difficulty_score":23,"last_commit_at":49,"category_tags":50,"status":16},2268,"ML-For-Beginners","microsoft\u002FML-For-Beginners","ML-For-Beginners 是由微软推出的一套系统化机器学习入门课程，旨在帮助零基础用户轻松掌握经典机器学习知识。这套课程将学习路径规划为 12 周，包含 26 节精炼课程和 52 道配套测验，内容涵盖从基础概念到实际应用的完整流程，有效解决了初学者面对庞大知识体系时无从下手、缺乏结构化指导的痛点。\n\n无论是希望转型的开发者、需要补充算法背景的研究人员，还是对人工智能充满好奇的普通爱好者，都能从中受益。课程不仅提供了清晰的理论讲解，还强调动手实践，让用户在循序渐进中建立扎实的技能基础。其独特的亮点在于强大的多语言支持，通过自动化机制提供了包括简体中文在内的 50 多种语言版本，极大地降低了全球不同背景用户的学习门槛。此外，项目采用开源协作模式，社区活跃且内容持续更新，确保学习者能获取前沿且准确的技术资讯。如果你正寻找一条清晰、友好且专业的机器学习入门之路，ML-For-Beginners 将是理想的起点。",84991,"2026-04-05T10:45:23",[14,51,52,53,15,54,26,13,55],"数据工具","视频","插件","其他","音频",{"id":57,"name":58,"github_repo":59,"description_zh":60,"stars":61,"difficulty_score":10,"last_commit_at":62,"category_tags":63,"status":16},3128,"ragflow","infiniflow\u002Fragflow","RAGFlow 是一款领先的开源检索增强生成（RAG）引擎，旨在为大语言模型构建更精准、可靠的上下文层。它巧妙地将前沿的 RAG 技术与智能体（Agent）能力相结合，不仅支持从各类文档中高效提取知识，还能让模型基于这些知识进行逻辑推理和任务执行。\n\n在大模型应用中，幻觉问题和知识滞后是常见痛点。RAGFlow 通过深度解析复杂文档结构（如表格、图表及混合排版），显著提升了信息检索的准确度，从而有效减少模型“胡编乱造”的现象，确保回答既有据可依又具备时效性。其内置的智能体机制更进一步，使系统不仅能回答问题，还能自主规划步骤解决复杂问题。\n\n这款工具特别适合开发者、企业技术团队以及 AI 研究人员使用。无论是希望快速搭建私有知识库问答系统，还是致力于探索大模型在垂直领域落地的创新者，都能从中受益。RAGFlow 提供了可视化的工作流编排界面和灵活的 API 接口，既降低了非算法背景用户的上手门槛，也满足了专业开发者对系统深度定制的需求。作为基于 Apache 2.0 协议开源的项目，它正成为连接通用大模型与行业专有知识之间的重要桥梁。",77062,"2026-04-04T04:44:48",[15,14,13,26,54],{"id":65,"github_repo":66,"name":67,"description_en":68,"description_zh":69,"ai_summary_zh":70,"readme_en":71,"readme_zh":72,"quickstart_zh":73,"use_case_zh":74,"hero_image_url":75,"owner_login":76,"owner_name":77,"owner_avatar_url":78,"owner_bio":79,"owner_company":80,"owner_location":80,"owner_email":81,"owner_twitter":80,"owner_website":82,"owner_url":83,"languages":84,"stars":93,"forks":94,"last_commit_at":95,"license":96,"difficulty_score":23,"env_os":97,"env_gpu":97,"env_ram":97,"env_deps":98,"category_tags":104,"github_topics":105,"view_count":10,"oss_zip_url":80,"oss_zip_packed_at":80,"status":16,"created_at":113,"updated_at":114,"faqs":115,"releases":146},224,"google-gemini-php\u002Flaravel","laravel","⚡️ Gemini PHP for Laravel is a community-maintained PHP API client that allows you to interact with the Gemini AI API.","Laravel 开发者可以借助 **Gemini PHP for Laravel** 轻松集成 Google 的 Gemini AI 能力。这是一个由社区维护的 PHP 客户端，专为 Laravel 框架设计，让你在应用中调用 Gemini API 实现文本生成、多模态输入（如图文、视频）、对话聊天、函数调用、内容嵌入等多种 AI 功能。\n\n它解决了 Laravel 项目中接入大模型 API 的复杂性问题，通过简洁的配置和丰富的功能封装，省去了手动处理 HTTP 请求、数据格式和流式响应的麻烦。只需一条 Composer 命令安装，并配置 API 密钥，即可快速启用 Gemini 的各项能力。\n\n该工具主要面向使用 Laravel 框架的 PHP 开发者，尤其适合希望在 Web 应用中集成 AI 功能（如智能客服、内容生成、图像理解等）的后端工程师或全栈开发者。普通用户或非技术角色通常不直接使用。\n\n值得一提的是，它支持 Gemini 的高级特性，如结构化输出、Google 搜索增强（Grounding）、语音生成、缓存内容管理以及流式响应，同时兼容 Laravel 的配置习惯和环境变","Laravel 开发者可以借助 **Gemini PHP for Laravel** 轻松集成 Google 的 Gemini AI 能力。这是一个由社区维护的 PHP 客户端，专为 Laravel 框架设计，让你在应用中调用 Gemini API 实现文本生成、多模态输入（如图文、视频）、对话聊天、函数调用、内容嵌入等多种 AI 功能。\n\n它解决了 Laravel 项目中接入大模型 API 的复杂性问题，通过简洁的配置和丰富的功能封装，省去了手动处理 HTTP 请求、数据格式和流式响应的麻烦。只需一条 Composer 命令安装，并配置 API 密钥，即可快速启用 Gemini 的各项能力。\n\n该工具主要面向使用 Laravel 框架的 PHP 开发者，尤其适合希望在 Web 应用中集成 AI 功能（如智能客服、内容生成、图像理解等）的后端工程师或全栈开发者。普通用户或非技术角色通常不直接使用。\n\n值得一提的是，它支持 Gemini 的高级特性，如结构化输出、Google 搜索增强（Grounding）、语音生成、缓存内容管理以及流式响应，同时兼容 Laravel 的配置习惯和环境变量机制，兼顾灵活性与易用性。","\u003Cp align=\"center\">\n    \u003Cimg src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fgoogle-gemini-php_laravel_readme_e0fbd7a13a71.png\" width=\"600\" alt=\"Google Gemini PHP for Laravel\">\n    \u003Cp align=\"center\">\n        \u003Ca href=\"https:\u002F\u002Fpackagist.org\u002Fpackages\u002Fgoogle-gemini-php\u002Flaravel\">\u003Cimg alt=\"Latest Version\" src=\"https:\u002F\u002Fimg.shields.io\u002Fpackagist\u002Fv\u002Fgoogle-gemini-php\u002Flaravel\">\u003C\u002Fa>\n        \u003Ca href=\"https:\u002F\u002Fpackagist.org\u002Fpackages\u002Fgoogle-gemini-php\u002Flaravel\">\u003Cimg alt=\"License\" src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Flicense\u002Fgoogle-gemini-php\u002Flaravel\">\u003C\u002Fa>\n    \u003C\u002Fp>\n\u003C\u002Fp>\n\n------\n\n**Gemini PHP** for Laravel is a community-maintained PHP API client that allows you to interact with the Gemini AI API.\n\n- Fatih AYDIN [github.com\u002Faydinfatih](https:\u002F\u002Fgithub.com\u002Faydinfatih)\n- Vytautas Smilingis [github.com\u002FPlytas](https:\u002F\u002Fgithub.com\u002FPlytas)\n\nFor more information, take a look at the [google-gemini-php\u002Fclient](https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Fclient) repository.\n\n## Table of Contents\n- [Prerequisites](#prerequisites)\n- [Setup](#setup)\n    - [Installation](#installation)\n    - [Setup your API key](#setup-your-api-key)\n    - [Upgrade to 2.0](#upgrade-to-20)\n- [Usage](#usage)\n    - [Chat Resource](#chat-resource)\n        - [Text-only Input](#text-only-input)\n        - [Text-and-image Input](#text-and-image-input)\n        - [Text-and-video Input](#text-and-video-input)\n        - [Image Generation](#image-generation)\n        - [Multi-turn Conversations (Chat)](#multi-turn-conversations-chat)\n        - [Chat with Streaming](#chat-with-streaming)\n        - [Stream Generate Content](#stream-generate-content)\n        - [Structured Output](#structured-output)\n        - [Function calling](#function-calling)\n        - [Code Execution](#code-execution)\n        - [Grounding with Google Search](#grounding-with-google-search)\n        - [System Instructions](#system-instructions)\n        - [Speech generation](#speech-generation)\n        - [Thinking Mode](#thinking-mode)\n        - [Count tokens](#count-tokens)\n        - [Configuration](#configuration)\n    - [File Management](#file-management)\n        - [File Upload](#file-upload)\n        - [List Files](#list-files)\n        - [Get File Metadata](#get-file-metadata)\n        - [Delete File](#delete-file)\n    - [Cached Content](#cached-content)\n        - [Create Cached Content](#create-cached-content)\n        - [List Cached Content](#list-cached-content)\n        - [Get Cached Content](#get-cached-content)\n        - [Update Cached Content](#update-cached-content)\n        - [Delete Cached Content](#delete-cached-content)\n        - [Use Cached Content](#use-cached-content)\n    - [Embedding Resource](#embedding-resource)\n    - [Models](#models)\n        - [List Models](#list-models)\n        - [Get Model](#get-model)\n- [Troubleshooting](#troubleshooting)\n- [Testing](#testing)\n\n\n## Prerequisites\nTo complete this quickstart, make sure that your development environment meets the following requirements:\n\n- Requires [PHP 8.1+](https:\u002F\u002Fphp.net\u002Freleases\u002F)\n- Requires [Laravel 9,10,11,12](https:\u002F\u002Flaravel.com\u002F)\n\n## Setup\n\n### Installation\n\nFirst, install Gemini via the [Composer](https:\u002F\u002Fgetcomposer.org\u002F) package manager:\n\n```bash\ncomposer require google-gemini-php\u002Flaravel\n```\n\nNext, execute the install command:\n\n```bash\nphp artisan gemini:install\n```\n\nThis will create a config\u002Fgemini.php configuration file in your project, which you can modify to your needs using environment variables. Blank environment variables for the Gemini API key is already appended to your .env file.\n\n```\nGEMINI_API_KEY=\n```\n\nYou can also define the following environment variables.\n```\nGEMINI_BASE_URL=\nGEMINI_REQUEST_TIMEOUT=\n```\n\n\n### Setup your API key\nTo use the Gemini API, you'll need an API key. If you don't already have one, create a key in Google AI Studio.\n\n[Get an API key](https:\u002F\u002Faistudio.google.com\u002Fapp\u002Fapikey)\n\n### Upgrade to 2.0\n\nStarting 2.0 release this package will work only with Gemini v1beta API ([see API versions](https:\u002F\u002Fai.google.dev\u002Fgemini-api\u002Fdocs\u002Fapi-versions)).\n\nTo update, run this command:\n\n```bash\ncomposer require google-gemini-php\u002Flaravel:^2.0\n```\n\nThis release introduces support for new features:\n* Structured output\n* System instructions\n* File uploads\n* Function calling\n* Code execution\n* Grounding with Google Search\n* Cached content\n* Thinking model configuration\n* Speech model configuration\n\n`\\Gemini\\Enums\\ModelType` enum has been deprecated and will be removed in next major version. Together with this `Gemini::geminiPro()` and `Gemini::geminiFlash()` methods have been removed.\nWe suggest using `Gemini::generativeModel()` method and pass in the model string directly. All methods that had previously accepted `ModelType` enum now accept a `BackedEnum`. We recommend implementing your own enum for convenience.\n\nThere may be other breaking changes not listed here. If you encounter any issues, please submit an issue or a pull request.\n\n## Usage\n\nInteract with Gemini's API:\n\n```php\nuse Gemini\\Enums\\ModelVariation;\nuse Gemini\\GeminiHelper;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$result = Gemini::generativeModel(model: 'gemini-2.0-flash')->generateContent('Hello');\n\n$result->text(); \u002F\u002F Hello! How can I assist you today?\n\n\u002F\u002F Helper method usage\n$result = Gemini::generativeModel(\n    model: GeminiHelper::generateGeminiModel(\n        variation: ModelVariation::FLASH,\n        generation: 2.5,\n        version: \"preview-04-17\"\n    ), \u002F\u002F models\u002Fgemini-2.5-flash-preview-04-17\n)->generateContent('Hello');\n\n$result->text(); \u002F\u002F Hello! How can I assist you today?\n```\n\n### Chat Resource\n\nFor a complete list of supported input formats and methods in Gemini API v1, see the [models documentation](https:\u002F\u002Fai.google.dev\u002Fgemini-api\u002Fdocs\u002Fmodels).\n\n#### Text-only Input\nGenerate a response from the model given an input message.\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$result = Gemini::generativeModel(model: 'gemini-2.0-flash')->generateContent('Hello');\n\n$result->text(); \u002F\u002F Hello! How can I assist you today?\n```\n\n#### Text-and-image Input\nGenerate responses by providing both text prompts and images to the Gemini model.\n\n```php\nuse Gemini\\Data\\Blob;\nuse Gemini\\Enums\\MimeType;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$result = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->generateContent([\n        'What is this picture?',\n        new Blob(\n            mimeType: MimeType::IMAGE_JPEG,\n            data: base64_encode(\n                file_get_contents('https:\u002F\u002Fstorage.googleapis.com\u002Fgenerativeai-downloads\u002Fimages\u002Fscones.jpg')\n            )\n        )\n    ]);\n\n$result->text(); \u002F\u002F  The picture shows a table with a white tablecloth. On the table are two cups of coffee, a bowl of blueberries, a silver spoon, and some flowers. There are also some blueberry scones on the table.\n```\n\n#### Text-and-video Input\nProcess video content and get AI-generated descriptions using the Gemini API with an uploaded video file.\n\n```php\nuse Gemini\\Data\\UploadedFile;\nuse Gemini\\Enums\\MimeType;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$result = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->generateContent([\n        'What is this video?',\n        new UploadedFile(\n            fileUri: '123-456', \u002F\u002F accepts just the name or the full URI\n            mimeType: MimeType::VIDEO_MP4\n        )\n    ]);\n\n$result->text(); \u002F\u002F  The video shows...\n```\n\n#### Image Generation\nGenerate images from text prompts using the Imagen model.\n\n```php\nuse Gemini\\Data\\ImageConfig;\nuse Gemini\\Data\\GenerationConfig;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$imageConfig = new ImageConfig(aspectRatio: '16:9');\n$generationConfig = new GenerationConfig(imageConfig: $imageConfig);\n\n$response = Gemini::generativeModel(model: 'gemini-2.5-flash-image')\n    ->withGenerationConfig($generationConfig)\n    ->generateContent('Draw a futuristic city');\n\n\u002F\u002F Save the image\nfile_put_contents('image.png', base64_decode($response->parts()[0]->inlineData->data));\n```\n\n#### Multi-turn Conversations (Chat)\nUsing Gemini, you can build freeform conversations across multiple turns.\n\n```php\nuse Gemini\\Data\\Content;\nuse Gemini\\Enums\\Role;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$chat = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->startChat(history: [\n        Content::parse(part: 'The stories you write about what I have to say should be one line. Is that clear?'),\n        Content::parse(part: 'Yes, I understand. The stories I write about your input should be one line long.', role: Role::MODEL)\n    ]);\n\n$response = $chat->sendMessage('Create a story set in a quiet village in 1600s France');\necho $response->text(); \u002F\u002F Amidst rolling hills and winding cobblestone streets, the tranquil village of Beausoleil whispered tales of love, intrigue, and the magic of everyday life in 17th century France.\n\n$response = $chat->sendMessage('Rewrite the same story in 1600s England');\necho $response->text(); \u002F\u002F In the heart of England's lush countryside, amidst emerald fields and thatched-roof cottages, the village of Willowbrook unfolded a tapestry of love, mystery, and the enchantment of ordinary days in the 17th century.\n```\n\n#### Chat with Streaming\nYou can also stream the response in a chat session. The history is automatically updated with the full response after the stream completes.\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$chat = Gemini::generativeModel(model: 'gemini-2.0-flash')->startChat();\n\n$stream = $chat->streamSendMessage('Hello');\n\nforeach ($stream as $response) {\n    echo $response->text();\n}\n```\n\n#### Stream Generate Content\nBy default, the model returns a response after completing the entire generation process. You can achieve faster interactions by not waiting for the entire result, and instead use streaming to handle partial results.\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$stream = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->streamGenerateContent('Write long a story about a magic backpack.');\n\nforeach ($stream as $response) {\n    echo $response->text();\n}\n```\n\n#### Structured Output\nGemini generates unstructured text by default, but some applications require structured text. For these use cases, you can constrain Gemini to respond with JSON, a structured data format suitable for automated processing. You can also constrain the model to respond with one of the options specified in an enum.\n\n```php\nuse Gemini\\Data\\GenerationConfig;\nuse Gemini\\Data\\Schema;\nuse Gemini\\Enums\\DataType;\nuse Gemini\\Enums\\ResponseMimeType;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$result = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->withGenerationConfig(\n        generationConfig: new GenerationConfig(\n            responseMimeType: ResponseMimeType::APPLICATION_JSON,\n            responseSchema: new Schema(\n                type: DataType::ARRAY,\n                items: new Schema(\n                    type: DataType::OBJECT,\n                    properties: [\n                        'recipe_name' => new Schema(type: DataType::STRING),\n                        'cooking_time_in_minutes' => new Schema(type: DataType::INTEGER)\n                    ],\n                    required: ['recipe_name', 'cooking_time_in_minutes'],\n                )\n            )\n        )\n    )\n    ->generateContent('List 5 popular cookie recipes with cooking time');\n\n$result->json();\n\n\u002F\u002F[\n\u002F\u002F    {\n\u002F\u002F      +\"cooking_time_in_minutes\": 10,\n\u002F\u002F      +\"recipe_name\": \"Chocolate Chip Cookies\",\n\u002F\u002F    },\n\u002F\u002F    {\n\u002F\u002F      +\"cooking_time_in_minutes\": 12,\n\u002F\u002F      +\"recipe_name\": \"Oatmeal Raisin Cookies\",\n\u002F\u002F    },\n\u002F\u002F    {\n\u002F\u002F      +\"cooking_time_in_minutes\": 10,\n\u002F\u002F      +\"recipe_name\": \"Peanut Butter Cookies\",\n\u002F\u002F    },\n\u002F\u002F    {\n\u002F\u002F      +\"cooking_time_in_minutes\": 10,\n\u002F\u002F      +\"recipe_name\": \"Snickerdoodles\",\n\u002F\u002F    },\n\u002F\u002F    {\n\u002F\u002F      +\"cooking_time_in_minutes\": 12,\n\u002F\u002F      +\"recipe_name\": \"Sugar Cookies\",\n\u002F\u002F    },\n\u002F\u002F  ]\n\n```\n\n#### Function calling\nGemini provides the ability to define and utilize custom functions that the model can call during conversations. This enables the model to perform specific actions or calculations through your defined functions.\n\n```php\n\u003C?php\n\nuse Gemini\\Data\\Content;\nuse Gemini\\Data\\FunctionCall;\nuse Gemini\\Data\\FunctionDeclaration;\nuse Gemini\\Data\\FunctionResponse;\nuse Gemini\\Data\\Part;\nuse Gemini\\Data\\Schema;\nuse Gemini\\Data\\Tool;\nuse Gemini\\Enums\\DataType;\nuse Gemini\\Enums\\Role;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\nfunction handleFunctionCall(FunctionCall $functionCall): Content\n{\n    if ($functionCall->name === 'addition') {\n        return new Content(\n            parts: [\n                new Part(\n                    functionResponse: new FunctionResponse(\n                        name: 'addition',\n                        response: ['answer' => $functionCall->args['number1'] + $functionCall->args['number2']],\n                    ),\n                    thoughtSignature: 'some-signature' \u002F\u002F Optional: Required for some models (e.g. Gemini 3 Pro)\n                )\n            ],\n            role: Role::USER\n        );\n    }\n\n    \u002F\u002FHandle other function calls\n}\n\n$chat = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->withTool(new Tool(\n        functionDeclarations: [\n            new FunctionDeclaration(\n                name: 'addition',\n                description: 'Performs addition',\n                parameters: new Schema(\n                    type: DataType::OBJECT,\n                    properties: [\n                        'number1' => new Schema(\n                            type: DataType::NUMBER,\n                            description: 'First number'\n                        ),\n                        'number2' => new Schema(\n                            type: DataType::NUMBER,\n                            description: 'Second number'\n                        ),\n                    ],\n                    required: ['number1', 'number2']\n                )\n            )\n        ]\n    ))\n    ->startChat();\n\n$response = $chat->sendMessage('What is 4 + 3?');\n\nif ($response->parts()[0]->functionCall !== null) {\n    $thoughtSignature = $response->parts()[0]->thoughtSignature; \u002F\u002F Access the thought signature\n    $functionResponse = handleFunctionCall($response->parts()[0]->functionCall);\n\n    $response = $chat->sendMessage($functionResponse);\n}\n\necho $response->text(); \u002F\u002F 4 + 3 = 7\n```\n\n#### Code Execution\nGemini models can generate and execute code automatically, and return the result to you. This is useful for tasks that require computation, data manipulation, or other programmatic operations.\n\n```php\nuse Gemini\\Data\\CodeExecution;\nuse Gemini\\Data\\Tool;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->withTool(new Tool(codeExecution: CodeExecution::from()))\n    ->generateContent('What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.');\n\n\u002F\u002F Access the executed code and results\nforeach ($response->parts() as $part) {\n    if ($part->executableCode !== null) {\n        echo \"Language: \" . $part->executableCode->language->value . \"\\n\";\n        echo \"Code: \" . $part->executableCode->code . \"\\n\";\n    }\n    if ($part->codeExecutionResult !== null) {\n        echo \"Outcome: \" . $part->codeExecutionResult->outcome->value . \"\\n\";\n        echo \"Output: \" . $part->codeExecutionResult->output . \"\\n\";\n    }\n}\n```\n\n#### Grounding with Google Search\nGrounding with Google Search connects the Gemini model to real-time web content and works with all available languages. This allows Gemini to provide more accurate answers and cite verifiable sources beyond its knowledge cutoff.\n\n**For Gemini 2.0 and later models (Recommended):**\n\nUse the simple `GoogleSearch` tool which automatically handles search queries:\n\n```php\nuse Gemini\\Data\\GoogleSearch;\nuse Gemini\\Data\\Tool;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->withTool(new Tool(googleSearch: GoogleSearch::from()))\n    ->generateContent('Who won the Euro 2024?');\n\necho $response->text();\n\u002F\u002F Spain won Euro 2024, defeating England 2-1 in the final.\n\n\u002F\u002F Access grounding metadata to see sources\n$groundingMetadata = $response->candidates[0]->groundingMetadata;\n\nif ($groundingMetadata !== null) {\n    \u002F\u002F Get the search queries that were executed\n    foreach ($groundingMetadata->webSearchQueries ?? [] as $query) {\n        echo \"Search query: {$query}\\n\";\n    }\n    \n    \u002F\u002F Get the web sources\n    foreach ($groundingMetadata->groundingChunks ?? [] as $chunk) {\n        if ($chunk->web !== null) {\n            echo \"Source: {$chunk->web->title} - {$chunk->web->uri}\\n\";\n        }\n    }\n    \n    \u002F\u002F Get grounding supports (links text segments to sources)\n    foreach ($groundingMetadata->groundingSupports ?? [] as $support) {\n        if ($support->segment !== null) {\n            echo \"Text segment: {$support->segment->text}\\n\";\n            echo \"Supported by chunks: \" . implode(', ', $support->groundingChunkIndices ?? []) . \"\\n\";\n        }\n    }\n}\n```\n\n#### System Instructions\nSystem instructions let you steer the behavior of the model based on your specific needs and use cases. You can set the role and personality of the model, define the format of responses, and provide goals and guardrails for model behavior.\n\n```php\nuse Gemini\\Data\\Content;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->withSystemInstruction(\n        Content::parse('You are a helpful assistant that always responds in the style of a pirate. Use nautical terms and pirate slang in all your responses.')\n    )\n    ->generateContent('Tell me about PHP programming');\n\necho $response->text();\n\u002F\u002F Ahoy there, matey! Let me tell ye about this fine treasure called PHP programming...\n```\n\nYou can also combine system instructions with other features:\n\n```php\nuse Gemini\\Data\\Content;\nuse Gemini\\Data\\GenerationConfig;\nuse Gemini\\Enums\\ResponseMimeType;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->withSystemInstruction(\n        Content::parse('You are a JSON API. Always respond with valid JSON objects. Be concise.')\n    )\n    ->withGenerationConfig(\n        new GenerationConfig(responseMimeType: ResponseMimeType::APPLICATION_JSON)\n    )\n    ->generateContent('Give me information about the Eiffel Tower');\n\nprint_r($response->json());\n```\n\n#### Speech generation\nGemini allows generating [speech from a text](https:\u002F\u002Fai.google.dev\u002Fgemini-api\u002Fdocs\u002Fspeech-generation). To use that, make sure to use a model that supports this functionality. The model will output base64 encoded audio string.\n\n##### Single speaker\n\n```php\nuse Gemini\\Data\\GenerationConfig;\nuse Gemini\\Data\\SpeechConfig;\nuse Gemini\\Data\\VoiceConfig;\nuse Gemini\\Data\\PrebuiltVoiceConfig;\nuse Gemini\\Enums\\ResponseModality;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::generativeModel('gemini-2.5-flash-preview-tts')->withGenerationConfig(\n    generationConfig: new GenerationConfig(\n        responseModalities: [ResponseModality::AUDIO],\n        speechConfig: new SpeechConfig(\n            voiceConfig: new VoiceConfig(\n                new PrebuiltVoiceConfig(voiceName: 'Kore')\n            ),\n        )\n    )\n)->generateContent(\"Say: Hello world\");\n\n\u002F\u002F The response contains base64 encoded audio\n$audioData = $response->parts()[0]->inlineData->data;\n```\n\n##### Multi speaker\n\n```php\nuse Gemini\\Data\\GenerationConfig;\nuse Gemini\\Data\\SpeechConfig;\nuse Gemini\\Data\\MultiSpeakerVoiceConfig;\nuse Gemini\\Data\\PrebuiltVoiceConfig;\nuse Gemini\\Data\\SpeakerVoiceConfig;\nuse Gemini\\Data\\VoiceConfig;\nuse Gemini\\Enums\\ResponseModality;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::generativeModel('gemini-2.5-flash-preview-tts')->withGenerationConfig(\n    generationConfig: new GenerationConfig(\n        responseModalities: [ResponseModality::AUDIO],\n        speechConfig: new SpeechConfig(\n            multiSpeakerVoiceConfig: new MultiSpeakerVoiceConfig([\n                new SpeakerVoiceConfig(\n                    speaker: 'Joe',\n                    voiceConfig: new VoiceConfig(\n                        new PrebuiltVoiceConfig('Kore'),\n                    )\n                ),\n                new SpeakerVoiceConfig(\n                    speaker: 'Jane',\n                    voiceConfig: new VoiceConfig(\n                        new PrebuiltVoiceConfig('Puck'),\n                    )\n                )\n            ]),\n            languageCode: 'en-GB'\n        )\n    )\n)->generateContent(\"TTS the following conversation between Joe and Jane:\\nJoe: How's it going today Jane?\\nJane: Not too bad, how about you?\");\n\n\u002F\u002F The response contains base64 encoded audio\n$audioData = $response->parts()[0]->inlineData->data;\n```\n\n#### Thinking Mode\nFor models that support thinking mode (like Gemini 2.0), you can configure the model to show its reasoning process. This is useful for complex problem-solving and understanding how the model arrives at its answers.\n\n```php\nuse Gemini\\Data\\GenerationConfig;\nuse Gemini\\Data\\ThinkingConfig;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::generativeModel(model: 'gemini-2.0-flash-thinking-exp')\n    ->withGenerationConfig(\n        new GenerationConfig(\n            thinkingConfig: new ThinkingConfig(\n                includeThoughts: true,\n                thinkingBudget: 1024\n            )\n        )\n    )\n    ->generateContent('Solve this logic puzzle: If all Bloops are Razzies and all Razzies are Lazzies, are all Bloops definitely Lazzies?');\n\n\u002F\u002F Access the model's thoughts and final answer\nforeach ($response->candidates[0]->content->parts as $part) {\n    if ($part->thought === true) {\n        \u002F\u002F This part contains the model's thinking process\n        echo \"Model's thinking: \" . $part->text . \"\\n\\n\";\n    } else if ($part->text !== null) {\n        \u002F\u002F This is the final answer\n        echo \"Final answer: \" . $part->text . \"\\n\";\n    }\n}\n```\n\n#### Count tokens\nWhen using long prompts, it might be useful to count tokens before sending any content to the model.\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->countTokens('Write a story about a magic backpack.');\n\necho $response->totalTokens; \u002F\u002F 9\n```\n\n#### Configuration\nEvery prompt you send to the model includes parameter values that control how the model generates a response. The model can generate different results for different parameter values. Learn more about [model parameters](https:\u002F\u002Fai.google.dev\u002Fdocs\u002Fconcepts#model_parameters).\n\nAlso, you can use safety settings to adjust the likelihood of getting responses that may be considered harmful. By default, safety settings block content with medium and\u002For high probability of being unsafe content across all dimensions. Learn more about [safety settings](https:\u002F\u002Fai.google.dev\u002Fdocs\u002Fconcepts#safety_setting).\n\n\n```php\nuse Gemini\\Data\\GenerationConfig;\nuse Gemini\\Enums\\HarmBlockThreshold;\nuse Gemini\\Data\\SafetySetting;\nuse Gemini\\Enums\\HarmCategory;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$safetySettingDangerousContent = new SafetySetting(\n    category: HarmCategory::HARM_CATEGORY_DANGEROUS_CONTENT,\n    threshold: HarmBlockThreshold::BLOCK_ONLY_HIGH\n);\n\n$safetySettingHateSpeech = new SafetySetting(\n    category: HarmCategory::HARM_CATEGORY_HATE_SPEECH,\n    threshold: HarmBlockThreshold::BLOCK_ONLY_HIGH\n);\n\n$generationConfig = new GenerationConfig(\n    stopSequences: [\n        'Title',\n    ],\n    maxOutputTokens: 800,\n    temperature: 1,\n    topP: 0.8,\n    topK: 10\n);\n\n$generativeModel = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->withSafetySetting($safetySettingDangerousContent)\n    ->withSafetySetting($safetySettingHateSpeech)\n    ->withGenerationConfig($generationConfig)\n    ->generateContent(\"Write a story about a magic backpack.\");\n```\n\n### File Management\n\nThe File API lets you store up to 20GB of files per project, with a per-file maximum size of 2GB. Files are stored for 48 hours and can be accessed in API calls.\n\n#### File Upload\nTo reference larger files and videos with various prompts, upload them to Gemini storage.\n\n```php\nuse Gemini\\Enums\\FileState;\nuse Gemini\\Enums\\MimeType;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$files = Gemini::files();\necho \"Uploading\\n\";\n$meta = $files->upload(\n    filename: 'video.mp4',\n    mimeType: MimeType::VIDEO_MP4,\n    displayName: 'Video'\n);\necho \"Processing\";\ndo {\n    echo \".\";\n    sleep(2);\n    $meta = $files->metadataGet($meta->uri);\n} while (!$meta->state->complete());\necho \"\\n\";\n\nif ($meta->state == FileState::Failed) {\n    die(\"Upload failed:\\n\" . json_encode($meta->toArray(), JSON_PRETTY_PRINT));\n}\n\necho \"Processing complete\\n\" . json_encode($meta->toArray(), JSON_PRETTY_PRINT);\necho \"\\n{$meta->uri}\";\n```\n\n#### List Files\nList all uploaded files in your project.\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::files()->list(pageSize: 10);\n\nforeach ($response->files as $file) {\n    echo \"Name: {$file->name}\\n\";\n    echo \"Display Name: {$file->displayName}\\n\";\n    echo \"Size: {$file->sizeBytes} bytes\\n\";\n    echo \"MIME Type: {$file->mimeType}\\n\";\n    echo \"State: {$file->state->value}\\n\";\n    echo \"---\\n\";\n}\n\n\u002F\u002F Get next page if available\nif ($response->nextPageToken) {\n    $nextPage = Gemini::files()->list(pageSize: 10, nextPageToken: $response->nextPageToken);\n}\n```\n\n#### Get File Metadata\nRetrieve metadata for a specific file.\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$meta = Gemini::files()->metadataGet('abc123');\n\n\u002F\u002F or use the full URI\n$meta = Gemini::files()->metadataGet($file->uri);\n\necho \"File: {$meta->displayName}\\n\";\necho \"State: {$meta->state->value}\\n\";\necho \"Size: {$meta->sizeBytes} bytes\\n\";\n```\n\n#### Delete File\nDelete a file from Gemini storage.\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\nGemini::files()->delete('files\u002Fabc123');\n\n\u002F\u002F or use the full URI\nGemini::files()->delete($file->uri);\n```\n\n### Cached Content\n\nContext caching allows you to save and reuse precomputed input tokens for frequently used content. This reduces costs and latency for requests with large amounts of shared context.\n\n#### Create Cached Content\nCache content that you'll reuse across multiple requests.\n\n```php\nuse Gemini\\Data\\Content;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$cachedContent = Gemini::cachedContents()->create(\n    model: 'gemini-2.0-flash',\n    systemInstruction: Content::parse('You are an expert PHP developer.'),\n    parts: [\n        'This is a large codebase...',\n        'File 1 contents...',\n        'File 2 contents...'\n    ],\n    ttl: '3600s', \u002F\u002F Cache for 1 hour\n    displayName: 'PHP Codebase Cache'\n);\n\necho \"Cached content created: {$cachedContent->name}\\n\";\n```\n\n#### List Cached Content\nList all cached content in your project.\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::cachedContents()->list(pageSize: 10);\n\nforeach ($response->cachedContents as $cached) {\n    echo \"Name: {$cached->name}\\n\";\n    echo \"Display Name: {$cached->displayName}\\n\";\n    echo \"Model: {$cached->model}\\n\";\n    echo \"Expires: {$cached->expireTime}\\n\";\n    echo \"---\\n\";\n}\n```\n\n#### Get Cached Content\nRetrieve a specific cached content by name.\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$cached = Gemini::cachedContents()->retrieve('cachedContents\u002Fabc123');\n\necho \"Model: {$cached->model}\\n\";\necho \"Created: {$cached->createTime}\\n\";\necho \"Expires: {$cached->expireTime}\\n\";\n```\n\n#### Update Cached Content\nUpdate the expiration time of cached content.\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n\u002F\u002F Extend by TTL\n$updated = Gemini::cachedContents()->update(\n    name: 'cachedContents\u002Fabc123',\n    ttl: '7200s' \u002F\u002F Extend by 2 hours\n);\n\n\u002F\u002F Or set absolute expiration time\n$updated = Gemini::cachedContents()->update(\n    name: 'cachedContents\u002Fabc123',\n    expireTime: '2024-12-31T23:59:59Z'\n);\n```\n\n#### Delete Cached Content\nDelete cached content when no longer needed.\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\nGemini::cachedContents()->delete('cachedContents\u002Fabc123');\n```\n\n#### Use Cached Content\nUse cached content in your requests to save tokens and reduce latency.\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->withCachedContent('cachedContents\u002Fabc123')\n    ->generateContent('Explain the main function in this codebase');\n\necho $response->text();\n\n\u002F\u002F Check token usage\necho \"Cached tokens used: {$response->usageMetadata->cachedContentTokenCount}\\n\";\necho \"New tokens used: {$response->usageMetadata->promptTokenCount}\\n\";\n```\n\n### Embedding Resource\nEmbedding is a technique used to represent information as a list of floating point numbers in an array. With Gemini, you can represent text (words, sentences, and blocks of text) in a vectorized form, making it easier to compare and contrast embeddings. For example, two texts that share a similar subject matter or sentiment should have similar embeddings, which can be identified through mathematical comparison techniques such as cosine similarity.\n\nUse the `text-embedding-004` model with either `embedContents` or `batchEmbedContents`:\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::embeddingModel('text-embedding-004')\n    ->embedContent(\"Write a story about a magic backpack.\");\n\nprint_r($response->embedding->values);\n\u002F\u002F[\n\u002F\u002F    [0] => 0.008624583\n\u002F\u002F    [1] => -0.030451821\n\u002F\u002F    [2] => -0.042496547\n\u002F\u002F    [3] => -0.029230341\n\u002F\u002F    [4] => 0.05486475\n\u002F\u002F    [5] => 0.006694871\n\u002F\u002F    [6] => 0.004025645\n\u002F\u002F    [7] => -0.007294857\n\u002F\u002F    [8] => 0.0057651913\n\u002F\u002F    ...\n\u002F\u002F]\n```\n\n### Models\n\nWe recommend checking [Google documentation](https:\u002F\u002Fai.google.dev\u002Fgemini-api\u002Fdocs\u002Fmodels) for the latest supported models.\n\n#### List Models\nUse list models to see the available Gemini models programmatically:\n\n- **pageSize (optional)**:\n  The maximum number of Models to return (per page). \u003Cbr>\n  If unspecified, 50 models will be returned per page. This method returns at most 1000 models per page, even if you pass a larger pageSize.\n\n- **nextPageToken (optional)**:\n  A page token, received from a previous models.list call. \u003Cbr>\n  Provide the pageToken returned by one request as an argument to the next request to retrieve the next page.\n  \n  When paginating, all other parameters provided to models.list must match the call that provided the page token.\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::models()->list(pageSize: 3, nextPageToken: 'ChFtb2RlbHMvZ2VtaW5pLXBybw==');\n\n$response->models;\n\u002F\u002F[\n\u002F\u002F    [0] => Gemini\\Data\\Model Object\n\u002F\u002F        (\n\u002F\u002F            [name] => models\u002Fgemini-2.0-flash\n\u002F\u002F            [version] => 2.0\n\u002F\u002F            [displayName] => Gemini 2.0 Flash\n\u002F\u002F            [description] => Gemini 2.0 Flash\n\u002F\u002F            ...\n\u002F\u002F        )\n\u002F\u002F    [1] => Gemini\\Data\\Model Object\n\u002F\u002F        (\n\u002F\u002F            [name] => models\u002Fgemini-2.5-pro-preview-05-06\n\u002F\u002F            [version] => 2.5-preview-05-06\n\u002F\u002F            [displayName] => Gemini 2.5 Pro Preview 05-06\n\u002F\u002F            [description] => Preview release (May 6th, 2025) of Gemini 2.5 Pro\n\u002F\u002F            ...\n\u002F\u002F        )\n\u002F\u002F    [2] => Gemini\\Data\\Model Object\n\u002F\u002F        (\n\u002F\u002F            [name] => models\u002Ftext-embedding-004\n\u002F\u002F            [version] => 004\n\u002F\u002F            [displayName] => Text Embedding 004\n\u002F\u002F            [description] => Obtain a distributed representation of a text.\n\u002F\u002F            ...\n\u002F\u002F        )\n\u002F\u002F]\n\n$response->nextPageToken \u002F\u002F Chltb2RlbHMvZ2VtaW5pLTEuMC1wcm8tMDAx\n```\n\n#### Get Model\nGet information about a model, such as version, display name, input token limit, etc.\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::models()->retrieve('models\u002Fgemini-2.5-pro-preview-05-06');\n\n$response->model;\n\u002F\u002FGemini\\Data\\Model Object\n\u002F\u002F(\n\u002F\u002F    [name] => models\u002Fgemini-2.5-pro-preview-05-06\n\u002F\u002F    [version] => 2.5-preview-05-06\n\u002F\u002F    [displayName] => Gemini 2.5 Pro Preview 05-06\n\u002F\u002F    [description] => Preview release (May 6th, 2025) of Gemini 2.5 Pro\n\u002F\u002F    ...\n\u002F\u002F)\n```\n\n## Troubleshooting\n\n### Timeout\n\nYou may run into a timeout when sending requests to the API. The default timeout depends on the HTTP client used.\n\nYou can configure the timeout in the `config\u002Fgemini.php` file:\n\n```php\nreturn [\n    'api_key' => env('GEMINI_API_KEY'),\n    'base_url' => env('GEMINI_BASE_URL', 'https:\u002F\u002Fgenerativelanguage.googleapis.com\u002Fv1beta\u002F'),\n    'request_timeout' => env('GEMINI_REQUEST_TIMEOUT', 30), \u002F\u002F Increase timeout to 30 seconds\n];\n```\n\nOr set it in your `.env` file:\n\n```env\nGEMINI_REQUEST_TIMEOUT=60\n```\n\n## Testing\n\nThe package provides a fake implementation of the `Gemini\\Client` class that allows you to fake the API responses.\n\nTo test your code ensure you swap the `Gemini\\Client` class with the `Gemini\\Testing\\ClientFake` class in your test case.\n\nThe fake responses are returned in the order they are provided while creating the fake client.\n\nAll responses are having a `fake()` method that allows you to easily create a response object by only providing the parameters relevant for your test case.\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\nuse Gemini\\Responses\\GenerativeModel\\GenerateContentResponse;\n\nGemini::fake([\n    GenerateContentResponse::fake([\n        'candidates' => [\n            [\n                'content' => [\n                    'parts' => [\n                        [\n                            'text' => 'success',\n                        ],\n                    ],\n                ],\n            ],\n        ],\n    ]),\n]);\n\n$result = Gemini::generativeModel(model: 'gemini-2.0-flash')->generateContent('test');\n\nexpect($result->text())->toBe('success');\n```\n\nIn case of a streamed response you can optionally provide a resource holding the fake response data.\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\nuse Gemini\\Responses\\GenerativeModel\\GenerateContentResponse;\n\nGemini::fake([\n    GenerateContentResponse::fakeStream(),\n]);\n\n$result = Gemini::generativeModel(model: 'gemini-2.0-flash')->streamGenerateContent('Hello');\n\nexpect($response->getIterator()->current())\n    ->text()->toBe('In the bustling city of Aethelwood, where the cobblestone streets whispered');\n```\n\nAfter the requests have been sent there are various methods to ensure that the expected requests were sent:\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\nuse Gemini\\Resources\\GenerativeModel;\nuse Gemini\\Resources\\Models;\n\n\u002F\u002F assert list models request was sent\nGemini::models()->assertSent(callback: function ($method) {\n    return $method === 'list';\n});\n\u002F\u002F or\nGemini::assertSent(resource: Models::class, callback: function ($method) {\n    return $method === 'list';\n});\n\nGemini::generativeModel(model: 'gemini-2.0-flash')->assertSent(function (string $method, array $parameters) {\n    return $method === 'generateContent' &&\n        $parameters[0] === 'Hello';\n});\n\u002F\u002F or\nGemini::assertSent(resource: GenerativeModel::class, model: 'gemini-2.0-flash', callback: function (string $method, array $parameters) {\n    return $method === 'generateContent' &&\n        $parameters[0] === 'Hello';\n});\n\n\n\u002F\u002F assert 2 generative model requests were sent\nGemini::assertSent(resource: GenerativeModel::class, model: 'gemini-2.0-flash', callback: 2);\n\u002F\u002F or\nGemini::generativeModel(model: 'gemini-2.0-flash')->assertSent(2);\n\n\u002F\u002F assert no generative model requests were sent\nGemini::assertNotSent(resource: GenerativeModel::class, model: 'gemini-2.0-flash');\n\u002F\u002F or\nGemini::generativeModel(model: 'gemini-2.0-flash')->assertNotSent();\n\n\u002F\u002F assert no requests were sent\nGemini::assertNothingSent();\n```\n\nTo write tests expecting the API request to fail you can provide a `Throwable` object as the response.\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\nuse Gemini\\Exceptions\\ErrorException;\n\nGemini::fake([\n    new ErrorException([\n        'message' => 'The model `gemini-basic` does not exist',\n        'status' => 'INVALID_ARGUMENT',\n        'code' => 400,\n    ]),\n]);\n\n\u002F\u002F the `ErrorException` will be thrown\nGemini::generativeModel(model: 'gemini-2.0-flash')->generateContent('test');\n```\n","\u003Cp align=\"center\">\n    \u003Cimg src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fgoogle-gemini-php_laravel_readme_e0fbd7a13a71.png\" width=\"600\" alt=\"Google Gemini PHP for Laravel\">\n    \u003Cp align=\"center\">\n        \u003Ca href=\"https:\u002F\u002Fpackagist.org\u002Fpackages\u002Fgoogle-gemini-php\u002Flaravel\">\u003Cimg alt=\"Latest Version\" src=\"https:\u002F\u002Fimg.shields.io\u002Fpackagist\u002Fv\u002Fgoogle-gemini-php\u002Flaravel\">\u003C\u002Fa>\n        \u003Ca href=\"https:\u002F\u002Fpackagist.org\u002Fpackages\u002Fgoogle-gemini-php\u002Flaravel\">\u003Cimg alt=\"License\" src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Flicense\u002Fgoogle-gemini-php\u002Flaravel\">\u003C\u002Fa>\n    \u003C\u002Fp>\n\u003C\u002Fp>\n\n------\n\nLaravel 的 **Gemini PHP** 是一个社区维护的 PHP API 客户端，允许你与 Gemini AI API 进行交互。\n\n- Fatih AYDIN [github.com\u002Faydinfatih](https:\u002F\u002Fgithub.com\u002Faydinfatih)\n- Vytautas Smilingis [github.com\u002FPlytas](https:\u002F\u002Fgithub.com\u002FPlytas)\n\n更多信息请查看 [google-gemini-php\u002Fclient](https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Fclient) 仓库。\n\n## 目录\n- [先决条件](#先决条件)\n- [设置](#设置)\n    - [安装](#安装)\n    - [设置你的 API 密钥](#设置你的-api-密钥)\n    - [升级到 2.0](#升级到-20)\n- [使用方法](#使用方法)\n    - [聊天资源（Chat Resource）](#聊天资源chat-resource)\n        - [纯文本输入](#纯文本输入)\n        - [文本和图像输入](#文本和图像输入)\n        - [文本和视频输入](#文本和视频输入)\n        - [图像生成](#图像生成)\n        - [多轮对话（Chat）](#多轮对话chat)\n        - [带流式传输的聊天](#带流式传输的聊天)\n        - [流式生成内容](#流式生成内容)\n        - [结构化输出](#结构化输出)\n        - [函数调用（Function calling）](#函数调用function-calling)\n        - [代码执行（Code Execution）](#代码执行code-execution)\n        - [使用 Google 搜索进行事实核查（Grounding with Google Search）](#使用-google-搜索进行事实核查grounding-with-google-search)\n        - [系统指令（System Instructions）](#系统指令system-instructions)\n        - [语音生成（Speech generation）](#语音生成speech-generation)\n        - [思考模式（Thinking Mode）](#思考模式thinking-mode)\n        - [计算 token 数量](#计算-token-数量)\n        - [配置](#配置)\n    - [文件管理（File Management）](#文件管理file-management)\n        - [文件上传](#文件上传)\n        - [列出文件](#列出文件)\n        - [获取文件元数据](#获取文件元数据)\n        - [删除文件](#删除文件)\n    - [缓存内容（Cached Content）](#缓存内容cached-content)\n        - [创建缓存内容](#创建缓存内容)\n        - [列出缓存内容](#列出缓存内容)\n        - [获取缓存内容](#获取缓存内容)\n        - [更新缓存内容](#更新缓存内容)\n        - [删除缓存内容](#删除缓存内容)\n        - [使用缓存内容](#使用缓存内容)\n    - [嵌入资源（Embedding Resource）](#嵌入资源embedding-resource)\n    - [模型（Models）](#模型models)\n        - [列出模型](#列出模型)\n        - [获取模型](#获取模型)\n- [故障排除](#故障排除)\n- [测试](#测试)\n\n\n## 先决条件\n要完成本快速入门，请确保你的开发环境满足以下要求：\n\n- 需要 [PHP 8.1+](https:\u002F\u002Fphp.net\u002Freleases\u002F)\n- 需要 [Laravel 9,10,11,12](https:\u002F\u002Flaravel.com\u002F)\n\n## 设置\n\n### 安装\n\n首先，通过 [Composer](https:\u002F\u002Fgetcomposer.org\u002F) 包管理器安装 Gemini：\n\n```bash\ncomposer require google-gemini-php\u002Flaravel\n```\n\n接下来，执行安装命令：\n\n```bash\nphp artisan gemini:install\n```\n\n这将在你的项目中创建一个 `config\u002Fgemini.php` 配置文件，你可以使用环境变量根据需要进行修改。`.env` 文件中已经自动添加了空白的 Gemini API 密钥环境变量。\n\n```\nGEMINI_API_KEY=\n```\n\n你也可以定义以下环境变量。\n```\nGEMINI_BASE_URL=\nGEMINI_REQUEST_TIMEOUT=\n```\n\n\n### 设置你的 API 密钥\n要使用 Gemini API，你需要一个 API 密钥。如果你还没有密钥，请在 Google AI Studio 中创建一个。\n\n[获取 API 密钥](https:\u002F\u002Faistudio.google.com\u002Fapp\u002Fapikey)\n\n### 升级到 2.0\n\n从 2.0 版本开始，此包仅支持 Gemini v1beta API（[参见 API 版本](https:\u002F\u002Fai.google.dev\u002Fgemini-api\u002Fdocs\u002Fapi-versions)）。\n\n要更新，请运行以下命令：\n\n```bash\ncomposer require google-gemini-php\u002Flaravel:^2.0\n```\n\n此版本引入了对以下新功能的支持：\n* 结构化输出（Structured output）\n* 系统指令（System instructions）\n* 文件上传（File uploads）\n* 函数调用（Function calling）\n* 代码执行（Code execution）\n* 使用 Google 搜索进行事实核查（Grounding with Google Search）\n* 缓存内容（Cached content）\n* 思考模式配置（Thinking model configuration）\n* 语音模式配置（Speech model configuration）\n\n`\\Gemini\\Enums\\ModelType` 枚举已被弃用，并将在下一个主要版本中移除。同时，`Gemini::geminiPro()` 和 `Gemini::geminiFlash()` 方法也已被移除。\n我们建议使用 `Gemini::generativeModel()` 方法并直接传入模型字符串。所有之前接受 `ModelType` 枚举的方法现在都接受 `BackedEnum`。我们建议你为方便起见实现自己的枚举。\n\n此处可能未列出其他破坏性变更。如果你遇到任何问题，请提交 issue 或 pull request。\n\n## 使用方法\n\n与 Gemini API 交互：\n\n```php\nuse Gemini\\Enums\\ModelVariation;\nuse Gemini\\GeminiHelper;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$result = Gemini::generativeModel(model: 'gemini-2.0-flash')->generateContent('Hello');\n\n$result->text(); \u002F\u002F Hello! How can I assist you today?\n\n\u002F\u002F 辅助方法用法\n$result = Gemini::generativeModel(\n    model: GeminiHelper::generateGeminiModel(\n        variation: ModelVariation::FLASH,\n        generation: 2.5,\n        version: \"preview-04-17\"\n    ), \u002F\u002F models\u002Fgemini-2.5-flash-preview-04-17\n)->generateContent('Hello');\n\n$result->text(); \u002F\u002F Hello! How can I assist you today?\n```\n\n### 聊天资源（Chat Resource）\n\n有关 Gemini API v1 支持的完整输入格式和方法列表，请参阅 [模型文档](https:\u002F\u002Fai.google.dev\u002Fgemini-api\u002Fdocs\u002Fmodels)。\n\n#### 纯文本输入\n根据输入消息从模型生成响应。\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$result = Gemini::generativeModel(model: 'gemini-2.0-flash')->generateContent('Hello');\n\n$result->text(); \u002F\u002F Hello! How can I assist you today?\n```\n\n#### 文本和图像输入\n通过向 Gemini 模型提供文本提示和图像来生成响应。\n\n```php\nuse Gemini\\Data\\Blob;\nuse Gemini\\Enums\\MimeType;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$result = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->generateContent([\n        'What is this picture?',\n        new Blob(\n            mimeType: MimeType::IMAGE_JPEG,\n            data: base64_encode(\n                file_get_contents('https:\u002F\u002Fstorage.googleapis.com\u002Fgenerativeai-downloads\u002Fimages\u002Fscones.jpg')\n            )\n        )\n    ]);\n\n$result->text(); \u002F\u002F  The picture shows a table with a white tablecloth. On the table are two cups of coffee, a bowl of blueberries, a silver spoon, and some flowers. There are also some blueberry scones on the table.\n```\n\n#### 文本和视频输入\n使用上传的视频文件通过 Gemini API 处理视频内容并获取 AI 生成的描述。\n\n```php\nuse Gemini\\Data\\UploadedFile;\nuse Gemini\\Enums\\MimeType;\nuse Gemini\\Laravel\\Facades\\Gemini;\n```\n\n$result = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->generateContent([\n        'What is this video?',\n        new UploadedFile(\n            fileUri: '123-456', \u002F\u002F accepts just the name or the full URI\n            mimeType: MimeType::VIDEO_MP4\n        )\n    ]);\n\n$result->text(); \u002F\u002F  The video shows...\n```\n\n#### 图像生成（Image Generation）\n使用 Imagen 模型根据文本提示生成图像。\n\n```php\nuse Gemini\\Data\\ImageConfig;\nuse Gemini\\Data\\GenerationConfig;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$imageConfig = new ImageConfig(aspectRatio: '16:9');\n$generationConfig = new GenerationConfig(imageConfig: $imageConfig);\n\n$response = Gemini::generativeModel(model: 'gemini-2.5-flash-image')\n    ->withGenerationConfig($generationConfig)\n    ->generateContent('Draw a futuristic city');\n\n\u002F\u002F Save the image\nfile_put_contents('image.png', base64_decode($response->parts()[0]->inlineData->data));\n```\n\n#### 多轮对话（Multi-turn Conversations，Chat）\n使用 Gemini，你可以构建跨越多轮的自由形式对话。\n\n```php\nuse Gemini\\Data\\Content;\nuse Gemini\\Enums\\Role;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$chat = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->startChat(history: [\n        Content::parse(part: 'The stories you write about what I have to say should be one line. Is that clear?'),\n        Content::parse(part: 'Yes, I understand. The stories I write about your input should be one line long.', role: Role::MODEL)\n    ]);\n\n$response = $chat->sendMessage('Create a story set in a quiet village in 1600s France');\necho $response->text(); \u002F\u002F Amidst rolling hills and winding cobblestone streets, the tranquil village of Beausoleil whispered tales of love, intrigue, and the magic of everyday life in 17th century France.\n\n$response = $chat->sendMessage('Rewrite the same story in 1600s England');\necho $response->text(); \u002F\u002F In the heart of England's lush countryside, amidst emerald fields and thatched-roof cottages, the village of Willowbrook unfolded a tapestry of love, mystery, and the enchantment of ordinary days in the 17th century.\n```\n\n#### 带流式传输的聊天（Chat with Streaming）\n你也可以在聊天会话中以流式方式接收响应。流式传输完成后，历史记录会自动更新为完整的响应内容。\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$chat = Gemini::generativeModel(model: 'gemini-2.0-flash')->startChat();\n\n$stream = $chat->streamSendMessage('Hello');\n\nforeach ($stream as $response) {\n    echo $response->text();\n}\n```\n\n#### 流式生成内容（Stream Generate Content）\n默认情况下，模型会在完成整个生成过程后返回响应。为了实现更快的交互，你可以不等待完整结果，而是使用流式传输来处理部分结果。\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$stream = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->streamGenerateContent('Write long a story about a magic backpack.');\n\nforeach ($stream as $response) {\n    echo $response->text();\n}\n```\n\n#### 结构化输出（Structured Output）\nGemini 默认生成非结构化文本，但某些应用需要结构化文本。针对这些场景，你可以约束 Gemini 以 JSON 格式（一种适合自动化处理的结构化数据格式）进行响应。你还可以约束模型仅从枚举（enum）中指定的选项中选择响应。\n\n```php\nuse Gemini\\Data\\GenerationConfig;\nuse Gemini\\Data\\Schema;\nuse Gemini\\Enums\\DataType;\nuse Gemini\\Enums\\ResponseMimeType;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$result = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->withGenerationConfig(\n        generationConfig: new GenerationConfig(\n            responseMimeType: ResponseMimeType::APPLICATION_JSON,\n            responseSchema: new Schema(\n                type: DataType::ARRAY,\n                items: new Schema(\n                    type: DataType::OBJECT,\n                    properties: [\n                        'recipe_name' => new Schema(type: DataType::STRING),\n                        'cooking_time_in_minutes' => new Schema(type: DataType::INTEGER)\n                    ],\n                    required: ['recipe_name', 'cooking_time_in_minutes'],\n                )\n            )\n        )\n    )\n    ->generateContent('List 5 popular cookie recipes with cooking time');\n\n$result->json();\n\n\u002F\u002F[\n\u002F\u002F    {\n\u002F\u002F      +\"cooking_time_in_minutes\": 10,\n\u002F\u002F      +\"recipe_name\": \"Chocolate Chip Cookies\",\n\u002F\u002F    },\n\u002F\u002F    {\n\u002F\u002F      +\"cooking_time_in_minutes\": 12,\n\u002F\u002F      +\"recipe_name\": \"Oatmeal Raisin Cookies\",\n\u002F\u002F    },\n\u002F\u002F    {\n\u002F\u002F      +\"cooking_time_in_minutes\": 10,\n\u002F\u002F      +\"recipe_name\": \"Peanut Butter Cookies\",\n\u002F\u002F    },\n\u002F\u002F    {\n\u002F\u002F      +\"cooking_time_in_minutes\": 10,\n\u002F\u002F      +\"recipe_name\": \"Snickerdoodles\",\n\u002F\u002F    },\n\u002F\u002F    {\n\u002F\u002F      +\"cooking_time_in_minutes\": 12,\n\u002F\u002F      +\"recipe_name\": \"Sugar Cookies\",\n\u002F\u002F    },\n\u002F\u002F  ]\n\n```\n\n#### 函数调用（Function calling）\nGemini 支持定义和使用自定义函数，模型可以在对话过程中调用这些函数。这使得模型能够通过你定义的函数执行特定操作或计算。\n\n```php\n\u003C?php\n\nuse Gemini\\Data\\Content;\nuse Gemini\\Data\\FunctionCall;\nuse Gemini\\Data\\FunctionDeclaration;\nuse Gemini\\Data\\FunctionResponse;\nuse Gemini\\Data\\Part;\nuse Gemini\\Data\\Schema;\nuse Gemini\\Data\\Tool;\nuse Gemini\\Enums\\DataType;\nuse Gemini\\Enums\\Role;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\nfunction handleFunctionCall(FunctionCall $functionCall): Content\n{\n    if ($functionCall->name === 'addition') {\n        return new Content(\n            parts: [\n                new Part(\n                    functionResponse: new FunctionResponse(\n                        name: 'addition',\n                        response: ['answer' => $functionCall->args['number1'] + $functionCall->args['number2']],\n                    ),\n                    thoughtSignature: 'some-signature' \u002F\u002F 可选：某些模型（例如 Gemini 3 Pro）需要此参数\n                )\n            ],\n            role: Role::USER\n        );\n    }\n\n    \u002F\u002FHandle other function calls\n}\n\n$chat = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->withTool(new Tool(\n        functionDeclarations: [\n            new FunctionDeclaration(\n                name: 'addition',\n                description: 'Performs addition',\n                parameters: new Schema(\n                    type: DataType::OBJECT,\n                    properties: [\n                        'number1' => new Schema(\n                            type: DataType::NUMBER,\n                            description: 'First number'\n                        ),\n                        'number2' => new Schema(\n                            type: DataType::NUMBER,\n                            description: 'Second number'\n                        ),\n                    ],\n                    required: ['number1', 'number2']\n                )\n            )\n        ]\n    ))\n    ->startChat();\n\n$response = $chat->sendMessage('What is 4 + 3?');\n```\n\nif ($response->parts()[0]->functionCall !== null) {\n    $thoughtSignature = $response->parts()[0]->thoughtSignature; \u002F\u002F 访问思维签名（thought signature）\n    $functionResponse = handleFunctionCall($response->parts()[0]->functionCall);\n\n    $response = $chat->sendMessage($functionResponse);\n}\n\necho $response->text(); \u002F\u002F 4 + 3 = 7\n```\n\n#### 代码执行（Code Execution）\nGemini 模型可以自动生成并执行代码，并将结果返回给你。这对于需要计算、数据处理或其他编程操作的任务非常有用。\n\n```php\nuse Gemini\\Data\\CodeExecution;\nuse Gemini\\Data\\Tool;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->withTool(new Tool(codeExecution: CodeExecution::from()))\n    ->generateContent('前 50 个质数的和是多少？请生成并运行代码进行计算，并确保包含全部 50 个质数。');\n\n\u002F\u002F 访问已执行的代码和结果\nforeach ($response->parts() as $part) {\n    if ($part->executableCode !== null) {\n        echo \"Language: \" . $part->executableCode->language->value . \"\\n\";\n        echo \"Code: \" . $part->executableCode->code . \"\\n\";\n    }\n    if ($part->codeExecutionResult !== null) {\n        echo \"Outcome: \" . $part->codeExecutionResult->outcome->value . \"\\n\";\n        echo \"Output: \" . $part->codeExecutionResult->output . \"\\n\";\n    }\n}\n```\n\n#### 使用 Google 搜索进行事实核查（Grounding with Google Search）\n使用 Google 搜索进行事实核查可将 Gemini 模型连接到实时网络内容，并支持所有可用语言。这使得 Gemini 能够提供更准确的答案，并引用超出其知识截止日期的可验证来源。\n\n**适用于 Gemini 2.0 及更高版本模型（推荐）：**\n\n使用简单的 `GoogleSearch` 工具，它会自动处理搜索查询：\n\n```php\nuse Gemini\\Data\\GoogleSearch;\nuse Gemini\\Data\\Tool;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->withTool(new Tool(googleSearch: GoogleSearch::from()))\n    ->generateContent('谁赢得了 2024 年欧洲杯？');\n\necho $response->text();\n\u002F\u002F 西班牙赢得了 2024 年欧洲杯，在决赛中以 2-1 击败英格兰。\n\n\u002F\u002F 访问事实核查元数据以查看来源\n$groundingMetadata = $response->candidates[0]->groundingMetadata;\n\nif ($groundingMetadata !== null) {\n    \u002F\u002F 获取已执行的搜索查询\n    foreach ($groundingMetadata->webSearchQueries ?? [] as $query) {\n        echo \"Search query: {$query}\\n\";\n    }\n    \n    \u002F\u002F 获取网络来源\n    foreach ($groundingMetadata->groundingChunks ?? [] as $chunk) {\n        if ($chunk->web !== null) {\n            echo \"Source: {$chunk->web->title} - {$chunk->web->uri}\\n\";\n        }\n    }\n    \n    \u002F\u002F 获取事实核查支持信息（将文本片段与来源关联）\n    foreach ($groundingMetadata->groundingSupports ?? [] as $support) {\n        if ($support->segment !== null) {\n            echo \"Text segment: {$support->segment->text}\\n\";\n            echo \"Supported by chunks: \" . implode(', ', $support->groundingChunkIndices ?? []) . \"\\n\";\n        }\n    }\n}\n```\n\n#### 系统指令（System Instructions）\n系统指令允许你根据特定需求和使用场景引导模型的行为。你可以设定模型的角色和个性、定义响应格式，并为模型行为提供目标和约束。\n\n```php\nuse Gemini\\Data\\Content;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->withSystemInstruction(\n        Content::parse('你是一个乐于助人的助手，总是以海盗的风格回答问题。在所有回答中使用航海术语和海盗俚语。')\n    )\n    ->generateContent('给我讲讲 PHP 编程');\n\necho $response->text();\n\u002F\u002F 啊哈，伙计！让俺给你讲讲这个叫 PHP 编程的宝贝儿……\n```\n\n你也可以将系统指令与其他功能结合使用：\n\n```php\nuse Gemini\\Data\\Content;\nuse Gemini\\Data\\GenerationConfig;\nuse Gemini\\Enums\\ResponseMimeType;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->withSystemInstruction(\n        Content::parse('你是一个 JSON API。始终以有效的 JSON 对象进行响应。保持简洁。')\n    )\n    ->withGenerationConfig(\n        new GenerationConfig(responseMimeType: ResponseMimeType::APPLICATION_JSON)\n    )\n    ->generateContent('给我一些关于埃菲尔铁塔的信息');\n\nprint_r($response->json());\n```\n\n#### 语音生成（Speech generation）\nGemini 支持[从文本生成语音](https:\u002F\u002Fai.google.dev\u002Fgemini-api\u002Fdocs\u002Fspeech-generation)。要使用此功能，请确保使用支持该功能的模型。模型将输出 base64 编码的音频字符串。\n\n##### 单说话人\n\n```php\nuse Gemini\\Data\\GenerationConfig;\nuse Gemini\\Data\\SpeechConfig;\nuse Gemini\\Data\\VoiceConfig;\nuse Gemini\\Data\\PrebuiltVoiceConfig;\nuse Gemini\\Enums\\ResponseModality;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::generativeModel('gemini-2.5-flash-preview-tts')->withGenerationConfig(\n    generationConfig: new GenerationConfig(\n        responseModalities: [ResponseModality::AUDIO],\n        speechConfig: new SpeechConfig(\n            voiceConfig: new VoiceConfig(\n                new PrebuiltVoiceConfig(voiceName: 'Kore')\n            ),\n        )\n    )\n)->generateContent(\"Say: Hello world\");\n\n\u002F\u002F 响应包含 base64 编码的音频\n$audioData = $response->parts()[0]->inlineData->data;\n```\n\n##### 多说话人\n\n```php\nuse Gemini\\Data\\GenerationConfig;\nuse Gemini\\Data\\SpeechConfig;\nuse Gemini\\Data\\MultiSpeakerVoiceConfig;\nuse Gemini\\Data\\PrebuiltVoiceConfig;\nuse Gemini\\Data\\SpeakerVoiceConfig;\nuse Gemini\\Data\\VoiceConfig;\nuse Gemini\\Enums\\ResponseModality;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::generativeModel('gemini-2.5-flash-preview-tts')->withGenerationConfig(\n    generationConfig: new GenerationConfig(\n        responseModalities: [ResponseModality::AUDIO],\n        speechConfig: new SpeechConfig(\n            multiSpeakerVoiceConfig: new MultiSpeakerVoiceConfig([\n                new SpeakerVoiceConfig(\n                    speaker: 'Joe',\n                    voiceConfig: new VoiceConfig(\n                        new PrebuiltVoiceConfig('Kore'),\n                    )\n                ),\n                new SpeakerVoiceConfig(\n                    speaker: 'Jane',\n                    voiceConfig: new VoiceConfig(\n                        new PrebuiltVoiceConfig('Puck'),\n                    )\n                )\n            ]),\n            languageCode: 'en-GB'\n        )\n    )\n)->generateContent(\"TTS the following conversation between Joe and Jane:\\nJoe: How's it going today Jane?\\nJane: Not too bad, how about you?\");\n\n\u002F\u002F 响应包含 base64 编码的音频\n$audioData = $response->parts()[0]->inlineData->data;\n```\n\n#### 思考模式（Thinking Mode）\n对于支持思考模式的模型（如 Gemini 2.0），你可以配置模型以展示其推理过程。这在解决复杂问题以及理解模型如何得出答案时非常有用。\n\n```php\nuse Gemini\\Data\\GenerationConfig;\nuse Gemini\\Data\\ThinkingConfig;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::generativeModel(model: 'gemini-2.0-flash-thinking-exp')\n    ->withGenerationConfig(\n        new GenerationConfig(\n            thinkingConfig: new ThinkingConfig(\n                includeThoughts: true,\n                thinkingBudget: 1024\n            )\n        )\n    )\n    ->generateContent('Solve this logic puzzle: If all Bloops are Razzies and all Razzies are Lazzies, are all Bloops definitely Lazzies?');\n\n\u002F\u002F 访问模型的思考过程和最终答案\nforeach ($response->candidates[0]->content->parts as $part) {\n    if ($part->thought === true) {\n        \u002F\u002F 此部分内容包含模型的思考过程\n        echo \"Model's thinking: \" . $part->text . \"\\n\\n\";\n    } else if ($part->text !== null) {\n        \u002F\u002F 这是最终答案\n        echo \"Final answer: \" . $part->text . \"\\n\";\n    }\n}\n```\n\n#### 计算 Token 数量\n当你使用较长的提示（prompt）时，在将内容发送给模型之前计算 token 数量可能会很有用。\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->countTokens('Write a story about a magic backpack.');\n\necho $response->totalTokens; \u002F\u002F 9\n```\n\n#### 配置\n你发送给模型的每个提示都包含控制模型如何生成响应的参数值。对于不同的参数值，模型可能会生成不同的结果。了解更多关于 [模型参数（model parameters）](https:\u002F\u002Fai.google.dev\u002Fdocs\u002Fconcepts#model_parameters) 的信息。\n\n此外，你可以使用安全设置（safety settings）来调整收到可能被视为有害内容的响应的可能性。默认情况下，安全设置会阻止在所有维度上具有中等或高概率的不安全内容。了解更多关于 [安全设置（safety settings）](https:\u002F\u002Fai.google.dev\u002Fdocs\u002Fconcepts#safety_setting) 的信息。\n\n```php\nuse Gemini\\Data\\GenerationConfig;\nuse Gemini\\Enums\\HarmBlockThreshold;\nuse Gemini\\Data\\SafetySetting;\nuse Gemini\\Enums\\HarmCategory;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$safetySettingDangerousContent = new SafetySetting(\n    category: HarmCategory::HARM_CATEGORY_DANGEROUS_CONTENT,\n    threshold: HarmBlockThreshold::BLOCK_ONLY_HIGH\n);\n\n$safetySettingHateSpeech = new SafetySetting(\n    category: HarmCategory::HARM_CATEGORY_HATE_SPEECH,\n    threshold: HarmBlockThreshold::BLOCK_ONLY_HIGH\n);\n\n$generationConfig = new GenerationConfig(\n    stopSequences: [\n        'Title',\n    ],\n    maxOutputTokens: 800,\n    temperature: 1,\n    topP: 0.8,\n    topK: 10\n);\n\n$generativeModel = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->withSafetySetting($safetySettingDangerousContent)\n    ->withSafetySetting($safetySettingHateSpeech)\n    ->withGenerationConfig($generationConfig)\n    ->generateContent(\"Write a story about a magic backpack.\");\n```\n\n\n\n### 文件管理（File Management）\n\n文件 API 允许你每个项目最多存储 20GB 的文件，单个文件最大为 2GB。文件将保存 48 小时，并可在 API 调用中访问。\n\n#### 文件上传\n若要在各种提示中引用较大的文件和视频，请将它们上传到 Gemini 存储。\n\n```php\nuse Gemini\\Enums\\FileState;\nuse Gemini\\Enums\\MimeType;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$files = Gemini::files();\necho \"Uploading\\n\";\n$meta = $files->upload(\n    filename: 'video.mp4',\n    mimeType: MimeType::VIDEO_MP4,\n    displayName: 'Video'\n);\necho \"Processing\";\ndo {\n    echo \".\";\n    sleep(2);\n    $meta = $files->metadataGet($meta->uri);\n} while (!$meta->state->complete());\necho \"\\n\";\n\nif ($meta->state == FileState::Failed) {\n    die(\"Upload failed:\\n\" . json_encode($meta->toArray(), JSON_PRETTY_PRINT));\n}\n\necho \"Processing complete\\n\" . json_encode($meta->toArray(), JSON_PRETTY_PRINT);\necho \"\\n{$meta->uri}\";\n```\n\n#### 列出文件\n列出项目中所有已上传的文件。\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::files()->list(pageSize: 10);\n\nforeach ($response->files as $file) {\n    echo \"Name: {$file->name}\\n\";\n    echo \"Display Name: {$file->displayName}\\n\";\n    echo \"Size: {$file->sizeBytes} bytes\\n\";\n    echo \"MIME Type: {$file->mimeType}\\n\";\n    echo \"State: {$file->state->value}\\n\";\n    echo \"---\\n\";\n}\n\n\u002F\u002F 如果有下一页，则获取下一页\nif ($response->nextPageToken) {\n    $nextPage = Gemini::files()->list(pageSize: 10, nextPageToken: $response->nextPageToken);\n}\n```\n\n#### 获取文件元数据\n获取特定文件的元数据。\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$meta = Gemini::files()->metadataGet('abc123');\n\n\u002F\u002F 或使用完整 URI\n$meta = Gemini::files()->metadataGet($file->uri);\n\necho \"File: {$meta->displayName}\\n\";\necho \"State: {$meta->state->value}\\n\";\necho \"Size: {$meta->sizeBytes} bytes\\n\";\n```\n\n#### 删除文件\n从 Gemini 存储中删除文件。\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\nGemini::files()->delete('files\u002Fabc123');\n\n\u002F\u002F 或使用完整 URI\nGemini::files()->delete($file->uri);\n```\n\n### 缓存内容（Cached Content）\n\n上下文缓存（Context caching）允许你保存并重用预计算的输入 token，适用于频繁使用的共享内容。这可以降低具有大量共享上下文的请求的成本和延迟。\n\n#### 创建缓存内容\n缓存将在多个请求中重复使用的内容。\n\n```php\nuse Gemini\\Data\\Content;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$cachedContent = Gemini::cachedContents()->create(\n    model: 'gemini-2.0-flash',\n    systemInstruction: Content::parse('You are an expert PHP developer.'),\n    parts: [\n        'This is a large codebase...',\n        'File 1 contents...',\n        'File 2 contents...'\n    ],\n    ttl: '3600s', \u002F\u002F 缓存 1 小时\n    displayName: 'PHP Codebase Cache'\n);\n\necho \"Cached content created: {$cachedContent->name}\\n\";\n```\n\n#### 列出缓存内容\n列出项目中所有已缓存的内容。\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::cachedContents()->list(pageSize: 10);\n\nforeach ($response->cachedContents as $cached) {\n    echo \"Name: {$cached->name}\\n\";\n    echo \"Display Name: {$cached->displayName}\\n\";\n    echo \"Model: {$cached->model}\\n\";\n    echo \"Expires: {$cached->expireTime}\\n\";\n    echo \"---\\n\";\n}\n```\n\n#### 获取缓存内容\n通过名称检索特定的缓存内容。\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$cached = Gemini::cachedContents()->retrieve('cachedContents\u002Fabc123');\n\necho \"Model: {$cached->model}\\n\";\necho \"Created: {$cached->createTime}\\n\";\necho \"Expires: {$cached->expireTime}\\n\";\n```\n\n#### 更新缓存内容\n更新缓存内容的过期时间。\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n\u002F\u002F 通过 TTL 延长\n$updated = Gemini::cachedContents()->update(\n    name: 'cachedContents\u002Fabc123',\n    ttl: '7200s' \u002F\u002F 延长 2 小时\n);\n\n\u002F\u002F 或设置绝对过期时间\n$updated = Gemini::cachedContents()->update(\n    name: 'cachedContents\u002Fabc123',\n    expireTime: '2024-12-31T23:59:59Z'\n);\n```\n\n#### 删除缓存内容\n在不再需要时删除缓存内容。\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\nGemini::cachedContents()->delete('cachedContents\u002Fabc123');\n```\n\n#### 使用缓存内容\n在请求中使用缓存内容以节省 token 并降低延迟。\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->withCachedContent('cachedContents\u002Fabc123')\n    ->generateContent('Explain the main function in this codebase');\n\necho $response->text();\n\n\u002F\u002F 检查 token 使用情况\necho \"Cached tokens used: {$response->usageMetadata->cachedContentTokenCount}\\n\";\necho \"New tokens used: {$response->usageMetadata->promptTokenCount}\\n\";\n```\n\n### 嵌入资源（Embedding Resource）\n\n嵌入（Embedding）是一种将信息表示为浮点数数组的技术。通过 Gemini，你可以将文本（单词、句子和文本块）转换为向量化形式，从而更方便地进行比较和对比。例如，主题或情感相似的两段文本应具有相近的嵌入向量，可通过余弦相似度（cosine similarity）等数学比较方法识别。\n\n使用 `text-embedding-004` 模型，调用 `embedContents` 或 `batchEmbedContents`：\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::embeddingModel('text-embedding-004')\n    ->embedContent(\"Write a story about a magic backpack.\");\n\nprint_r($response->embedding->values);\n\u002F\u002F[\n\u002F\u002F    [0] => 0.008624583\n\u002F\u002F    [1] => -0.030451821\n\u002F\u002F    [2] => -0.042496547\n\u002F\u002F    [3] => -0.029230341\n\u002F\u002F    [4] => 0.05486475\n\u002F\u002F    [5] => 0.006694871\n\u002F\u002F    [6] => 0.004025645\n\u002F\u002F    [7] => -0.007294857\n\u002F\u002F    [8] => 0.0057651913\n\u002F\u002F    ...\n\u002F\u002F]\n```\n\n### 模型（Models）\n\n建议查阅 [Google 官方文档](https:\u002F\u002Fai.google.dev\u002Fgemini-api\u002Fdocs\u002Fmodels) 获取最新支持的模型列表。\n\n#### 列出模型\n通过编程方式查看可用的 Gemini 模型：\n\n- **pageSize（可选）**：  \n  每页返回的最大模型数量。  \n  若未指定，默认每页返回 50 个模型。即使传入更大的值，该方法每页最多也只返回 1000 个模型。\n\n- **nextPageToken（可选）**：  \n  从上一次 `models.list` 调用中获得的分页令牌。  \n  将前一次请求返回的 `pageToken` 作为参数传递给下一次请求，以获取下一页结果。  \n  分页时，除 `pageToken` 外，其他所有参数必须与提供该令牌的原始请求一致。\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::models()->list(pageSize: 3, nextPageToken: 'ChFtb2RlbHMvZ2VtaW5pLXBybw==');\n\n$response->models;\n\u002F\u002F[\n\u002F\u002F    [0] => Gemini\\Data\\Model Object\n\u002F\u002F        (\n\u002F\u002F            [name] => models\u002Fgemini-2.0-flash\n\u002F\u002F            [version] => 2.0\n\u002F\u002F            [displayName] => Gemini 2.0 Flash\n\u002F\u002F            [description] => Gemini 2.0 Flash\n\u002F\u002F            ...\n\u002F\u002F        )\n\u002F\u002F    [1] => Gemini\\Data\\Model Object\n\u002F\u002F        (\n\u002F\u002F            [name] => models\u002Fgemini-2.5-pro-preview-05-06\n\u002F\u002F            [version] => 2.5-preview-05-06\n\u002F\u002F            [displayName] => Gemini 2.5 Pro Preview 05-06\n\u002F\u002F            [description] => Preview release (May 6th, 2025) of Gemini 2.5 Pro\n\u002F\u002F            ...\n\u002F\u002F        )\n\u002F\u002F    [2] => Gemini\\Data\\Model Object\n\u002F\u002F        (\n\u002F\u002F            [name] => models\u002Ftext-embedding-004\n\u002F\u002F            [version] => 004\n\u002F\u002F            [displayName] => Text Embedding 004\n\u002F\u002F            [description] => Obtain a distributed representation of a text.\n\u002F\u002F            ...\n\u002F\u002F        )\n\u002F\u002F]\n\n$response->nextPageToken \u002F\u002F Chltb2RlbHMvZ2VtaW5pLTEuMC1wcm8tMDAx\n```\n\n#### 获取模型信息\n获取模型的详细信息，如版本、显示名称、输入 token 限制等。\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$response = Gemini::models()->retrieve('models\u002Fgemini-2.5-pro-preview-05-06');\n\n$response->model;\n\u002F\u002FGemini\\Data\\Model Object\n\u002F\u002F(\n\u002F\u002F    [name] => models\u002Fgemini-2.5-pro-preview-05-06\n\u002F\u002F    [version] => 2.5-preview-05-06\n\u002F\u002F    [displayName] => Gemini 2.5 Pro Preview 05-06\n\u002F\u002F    [description] => Preview release (May 6th, 2025) of Gemini 2.5 Pro\n\u002F\u002F    ...\n\u002F\u002F)\n```\n\n## 故障排除（Troubleshooting）\n\n### 超时（Timeout）\n\n向 API 发送请求时可能会遇到超时问题。默认超时时间取决于所使用的 HTTP 客户端。\n\n你可以在 `config\u002Fgemini.php` 文件中配置超时时间：\n\n```php\nreturn [\n    'api_key' => env('GEMINI_API_KEY'),\n    'base_url' => env('GEMINI_BASE_URL', 'https:\u002F\u002Fgenerativelanguage.googleapis.com\u002Fv1beta\u002F'),\n    'request_timeout' => env('GEMINI_REQUEST_TIMEOUT', 30), \u002F\u002F 将超时时间增加到 30 秒\n];\n```\n\n或者在 `.env` 文件中设置：\n\n```env\nGEMINI_REQUEST_TIMEOUT=60\n```\n\n## 测试（Testing）\n\n本包提供了一个 `Gemini\\Client` 类的模拟（fake）实现，允许你模拟 API 响应。\n\n为了测试你的代码，请确保在测试用例中将 `Gemini\\Client` 类替换为 `Gemini\\Testing\\ClientFake` 类。\n\n模拟响应会按照创建模拟客户端时提供的顺序依次返回。\n\n所有响应都包含一个 `fake()` 方法，让你只需提供与当前测试相关的参数，即可轻松创建响应对象。\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\nuse Gemini\\Responses\\GenerativeModel\\GenerateContentResponse;\n\nGemini::fake([\n    GenerateContentResponse::fake([\n        'candidates' => [\n            [\n                'content' => [\n                    'parts' => [\n                        [\n                            'text' => 'success',\n                        ],\n                    ],\n                ],\n            ],\n        ],\n    ]),\n]);\n\n$result = Gemini::generativeModel(model: 'gemini-2.0-flash')->generateContent('test');\n\nexpect($result->text())->toBe('success');\n```\n\n对于流式（streamed）响应，你可以选择性地提供一个包含模拟响应数据的资源（resource）。\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\nuse Gemini\\Responses\\GenerativeModel\\GenerateContentResponse;\n\nGemini::fake([\n    GenerateContentResponse::fakeStream(),\n]);\n\n$result = Gemini::generativeModel(model: 'gemini-2.0-flash')->streamGenerateContent('Hello');\n\nexpect($response->getIterator()->current())\n    ->text()->toBe('In the bustling city of Aethelwood, where the cobblestone streets whispered');\n```\n\n在请求发送后，你可以使用多种方法来验证是否发送了预期的请求：\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\nuse Gemini\\Resources\\GenerativeModel;\nuse Gemini\\Resources\\Models;\n\n\u002F\u002F 断言已发送列出模型（list models）的请求\nGemini::models()->assertSent(callback: function ($method) {\n    return $method === 'list';\n});\n\u002F\u002F 或\nGemini::assertSent(resource: Models::class, callback: function ($method) {\n    return $method === 'list';\n});\n\nGemini::generativeModel(model: 'gemini-2.0-flash')->assertSent(function (string $method, array $parameters) {\n    return $method === 'generateContent' &&\n        $parameters[0] === 'Hello';\n});\n\u002F\u002F 或\nGemini::assertSent(resource: GenerativeModel::class, model: 'gemini-2.0-flash', callback: function (string $method, array $parameters) {\n    return $method === 'generateContent' &&\n        $parameters[0] === 'Hello';\n});\n\n\n\u002F\u002F 断言已发送 2 次生成式模型（generative model）请求\nGemini::assertSent(resource: GenerativeModel::class, model: 'gemini-2.0-flash', callback: 2);\n\u002F\u002F 或\nGemini::generativeModel(model: 'gemini-2.0-flash')->assertSent(2);\n\n\u002F\u002F 断言未发送任何生成式模型请求\nGemini::assertNotSent(resource: GenerativeModel::class, model: 'gemini-2.0-flash');\n\u002F\u002F 或\nGemini::generativeModel(model: 'gemini-2.0-flash')->assertNotSent();\n\n\u002F\u002F 断言未发送任何请求\nGemini::assertNothingSent();\n```\n\n若要编写期望 API 请求失败的测试，你可以将一个 `Throwable` 对象作为响应提供。\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\nuse Gemini\\Exceptions\\ErrorException;\n\nGemini::fake([\n    new ErrorException([\n        'message' => 'The model `gemini-basic` does not exist',\n        'status' => 'INVALID_ARGUMENT',\n        'code' => 400,\n    ]),\n]);\n\n\u002F\u002F 将抛出 `ErrorException`\nGemini::generativeModel(model: 'gemini-2.0-flash')->generateContent('test');\n```","# Laravel Gemini AI 快速上手指南\n\n## 环境准备\n\n- **PHP 版本**：8.1 或更高\n- **Laravel 版本**：9、10、11 或 12\n\n> 💡 建议使用国内 Composer 镜像加速安装（如阿里云镜像）：\n> ```bash\n> composer config -g repo.packagist composer https:\u002F\u002Fmirrors.aliyun.com\u002Fcomposer\u002F\n> ```\n\n## 安装步骤\n\n1. 使用 Composer 安装扩展包：\n\n```bash\ncomposer require google-gemini-php\u002Flaravel\n```\n\n2. 执行安装命令，生成配置文件：\n\n```bash\nphp artisan gemini:install\n```\n\n该命令会在 `config\u002Fgemini.php` 创建配置文件，并在 `.env` 中自动添加如下环境变量占位符：\n\n```\nGEMINI_API_KEY=\nGEMINI_BASE_URL=\nGEMINI_REQUEST_TIMEOUT=\n```\n\n3. 获取 API 密钥  \n   访问 [Google AI Studio](https:\u002F\u002Faistudio.google.com\u002Fapp\u002Fapikey) 创建并复制你的 API Key，填入 `.env` 文件：\n\n```\nGEMINI_API_KEY=your_api_key_here\n```\n\n## 基本使用\n\n### 最简文本生成示例\n\n```php\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$result = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->generateContent('你好，介绍一下你自己');\n\necho $result->text(); \u002F\u002F 输出模型回复\n```\n\n### 多模态输入（文本 + 图片）\n\n```php\nuse Gemini\\Data\\Blob;\nuse Gemini\\Enums\\MimeType;\nuse Gemini\\Laravel\\Facades\\Gemini;\n\n$result = Gemini::generativeModel(model: 'gemini-2.0-flash')\n    ->generateContent([\n        '这张图片里有什么？',\n        new Blob(\n            mimeType: MimeType::IMAGE_JPEG,\n            data: base64_encode(file_get_contents('path\u002Fto\u002Fyour\u002Fimage.jpg'))\n        )\n    ]);\n\necho $result->text();\n```\n\n> ✅ 提示：推荐使用 `gemini-2.0-flash` 或 `gemini-2.5-flash` 等最新模型以支持全部功能。  \n> ⚠️ 注意：v2.0 起已移除 `Gemini::geminiPro()` 等旧方法，请统一使用 `generativeModel()` 并传入模型名称字符串。","一家电商 SaaS 平台的技术团队正在为商家后台开发一个“智能商品描述生成”功能，允许用户上传商品图片后，自动生成符合 SEO 规范的多语言文案。\n\n### 没有 laravel 时\n- 需手动封装 HTTP 请求调用 Gemini API，处理认证、重试、超时等逻辑，代码冗余且易出错  \n- 无法直接在 Laravel 项目中使用熟悉的 Facade 或依赖注入方式调用 AI 能力，集成成本高  \n- 处理图文混合输入（如上传商品图+文字提示）需自行实现文件上传、URI 构造和上下文管理  \n- 缺乏对流式响应、结构化输出等高级功能的封装，难以满足实时预览或格式化输出需求  \n- 每次升级 API 版本或调整配置都要修改底层调用逻辑，维护负担重  \n\n### 使用 laravel 后\n- 通过 `Gemini::chat()->textAndImage()` 一行代码即可完成图文联合推理，自动处理文件上传与上下文绑定  \n- 直接使用 Laravel 风格的链式调用和配置系统，API 密钥、超时等参数通过 `.env` 统一管理  \n- 内置对流式生成、结构化 JSON 输出、函数调用等高级特性的支持，轻松实现“边生成边展示”效果  \n- 借助 `php artisan gemini:install` 快速初始化配置，升级版本只需更新 Composer 包，无需重写集成代码  \n- 与 Laravel 的异常处理、日志系统无缝衔接，调试和监控更高效  \n\nlaravel 让 Laravel 开发者以原生方式高效、安全地调用 Gemini AI 能力，大幅降低 AI 功能落地门槛。","https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fgoogle-gemini-php_laravel_caf09651.png","google-gemini-php","Google Gemini PHP","https:\u002F\u002Foss.gittoolsai.com\u002Favatars\u002Fgoogle-gemini-php_71ca7bc1.png","Makes Google Gemini development in PHP more productive and enjoyable.",null,"aydinfatih52@gmail.com","https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Fclient","https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php",[85,89],{"name":86,"color":87,"percentage":88},"PHP","#4F5D95",99.9,{"name":90,"color":91,"percentage":92},"Hack","#878787",0.1,614,54,"2026-04-03T15:49:29","MIT","未说明",{"notes":99,"python":97,"dependencies":100},"该工具是 Laravel 的 PHP 扩展包，用于调用 Google Gemini AI API，需配置有效的 API 密钥。不涉及本地模型运行，因此对 GPU、内存等硬件无特殊要求。",[101,102,103],"PHP 8.1+","Laravel 9\u002F10\u002F11\u002F12","google-gemini-php\u002Fclient",[13,53],[106,107,108,109,110,67,111,112],"gemini","gemini-api","google-ai","google-ai-client-sdk","google-ai-studio","laravel-framework","laravel-package","2026-03-27T02:49:30.150509","2026-04-06T06:46:01.293812",[116,121,126,131,136,141],{"id":117,"question_zh":118,"answer_zh":119,"source_url":120},642,"如何让 Gemini API 返回标准的 JSON 格式响应？","需要在生成内容时指定响应 MIME 类型为 application\u002Fjson，并使用 json() 方法获取解析后的数据。示例代码：\n```php\n$model = \"gemini-1.5-flash\";\n$response = Gemini::generativeModel($model)\n    ->withGenerationConfig(\n        generationConfig: new GenerationConfig(\n            responseMimeType: ResponseMimeType::APPLICATION_JSON,\n        )\n    )\n    ->generateContent($prompt)\n    ->json();\n\ndd($response);\n```","https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel\u002Fissues\u002F22",{"id":122,"question_zh":123,"answer_zh":124,"source_url":125},643,"调用 generateContent() 后出现 'syntax error' 错误怎么办？","该错误通常是因为 API 返回的内容不是有效的 JSON，而代码试图将其解析为结构化数据。确保正确处理返回值，例如将 $result->text() 的结果赋值给一个变量（如 $res = $result->text()），或检查模型是否支持当前 API 版本。如果问题持续，可考虑直接使用 Guzzle 调用原始 HTTP API。","https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel\u002Fissues\u002F9",{"id":127,"question_zh":128,"answer_zh":129,"source_url":130},644,"为什么设置 GEMINI_REQUEST_TIMEOUT 为空会导致 'Unsupported operand types: string * int' 错误？","当 .env 文件中设置了 GEMINI_REQUEST_TIMEOUT= 但未赋值时，Guzzle 会接收到一个空字符串作为超时值，在内部计算时尝试将字符串与整数相乘，从而引发类型错误。解决方法是：要么删除该行配置，要么为其设置一个有效数值（如 GEMINI_REQUEST_TIMEOUT=30）。此问题已在 v2.0.2 版本中修复。","https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel\u002Fissues\u002F37",{"id":132,"question_zh":133,"answer_zh":134,"source_url":135},645,"出现 'models\u002Fgemini-pro is not found for API version v1' 错误如何解决？","从 v2.0 开始，gemini-pro 模型的调用方式已变更。应弃用 Gemini::geminiPro()，改用 Gemini::generativeModel('gemini-1.5-pro') 或其他有效模型名称。请参考升级指南：https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel#upgrade-to-20，并运行 composer update google-gemini-php\u002Flaravel 升级到最新版。","https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel\u002Fissues\u002F32",{"id":137,"question_zh":138,"answer_zh":139,"source_url":140},646,"为什么 .env 中留空 GEMINI_BASE_URL 或 GEMINI_REQUEST_TIMEOUT 会导致程序崩溃？","当这些环境变量被声明但值为空时（如 #GEMINI_BASE_URL=），底层库会将其视为字符串空值，在类型敏感的操作中（如超时计算）引发错误。解决方案是：注释掉或完全删除这些未使用的配置行，而不是保留空值。","https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel\u002Fissues\u002F3",{"id":142,"question_zh":143,"answer_zh":144,"source_url":145},647,"遇到 UnserializableResponse: Syntax error 错误该如何处理？","该错误表明 API 返回的内容无法被解析为有效 JSON。可能原因包括模型行为不一致、API 响应格式异常或库版本兼容性问题。建议：1) 确认使用的模型名称正确；2) 检查 PHP 和库版本兼容性；3) 如急需上线，可临时绕过该库，直接使用 Guzzle 发送 HTTP 请求调用 Gemini 原始 API。","https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel\u002Fissues\u002F38",[147,152,157,162,167,172,177,182,187],{"id":148,"version":149,"summary_zh":150,"released_at":151},100236,"2.0.3","**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel\u002Fcompare\u002F2.0.2...2.0.3","2025-11-25T15:35:02",{"id":153,"version":154,"summary_zh":155,"released_at":156},100237,"2.0.2","refactor: Update parameter type in fake method to mixed\r\nrefactor: Use config()->integer for request timeout in GuzzleClient\r\n\r\n\r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel\u002Fcompare\u002F2.0.1...2.0.2","2025-11-22T20:36:35",{"id":158,"version":159,"summary_zh":160,"released_at":161},100238,"2.0.1","## What's Changed\r\n* Check for env file existence by @Plytas in https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel\u002Fpull\u002F35\r\n\r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel\u002Fcompare\u002F2.0.0...2.0.1","2025-05-12T15:57:05",{"id":163,"version":164,"summary_zh":165,"released_at":166},100239,"2.0.0","## What's Changed\r\nMore information: https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Fclient\u002Freleases\u002Ftag\u002F2.0.0\r\n\r\n* Updated to 2.0 by @Plytas in https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel\u002Fpull\u002F33\r\n\r\n## New Contributors\r\n* @Plytas made their first contribution in https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel\u002Fpull\u002F33\r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel\u002Fcompare\u002F1.0.2...2.0.0","2025-05-09T15:56:51",{"id":168,"version":169,"summary_zh":170,"released_at":171},100240,"1.0.2","## What's Changed\r\n* Support Laravel 12 by @jeroenqui in https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel\u002Fpull\u002F29\r\n\r\n## New Contributors\r\n* @jeroenqui made their first contribution in https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel\u002Fpull\u002F29\r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel\u002Fcompare\u002F1.0.1...1.0.2","2025-02-27T05:51:53",{"id":173,"version":174,"summary_zh":175,"released_at":176},100241,"1.0.1-beta","## What's Changed\r\n* Support Laravel 12 by @jeroenqui in https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel\u002Fpull\u002F29\r\n\r\n## New Contributors\r\n* @jeroenqui made their first contribution in https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel\u002Fpull\u002F29\r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel\u002Fcompare\u002F1.0.0-beta...1.0.1-beta","2025-02-27T05:55:01",{"id":178,"version":179,"summary_zh":180,"released_at":181},100242,"1.0.0-beta","**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fgoogle-gemini-php\u002Flaravel\u002Fcompare\u002F1.0.1...1.0.0-beta","2024-09-28T19:46:43",{"id":183,"version":184,"summary_zh":185,"released_at":186},100243,"1.0.1","### Fixed \r\n- Updated docblocs","2024-02-11T17:26:45",{"id":188,"version":189,"summary_zh":190,"released_at":191},100244,"1.0.0","Initial release","2024-02-11T17:19:51"]