{"id":21803023,"url":"https://github.com/litongjava/java-openai","last_synced_at":"2025-03-21T07:16:14.879Z","repository":{"id":247000348,"uuid":"822072904","full_name":"litongjava/java-openai","owner":"litongjava","description":"a robust client library for integrating OpenAI services into Java applications","archived":false,"fork":false,"pushed_at":"2025-03-19T08:30:36.000Z","size":187,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-19T09:30:23.453Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/litongjava.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-30T08:31:26.000Z","updated_at":"2025-03-19T08:30:39.000Z","dependencies_parsed_at":"2024-07-06T04:24:17.922Z","dependency_job_id":"a918aa2b-a369-4d7f-ba04-8549ff9434b7","html_url":"https://github.com/litongjava/java-openai","commit_stats":null,"previous_names":["litongjava/java-openai"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/litongjava%2Fjava-openai","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/litongjava%2Fjava-openai/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/litongjava%2Fjava-openai/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/litongjava%2Fjava-openai/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/litongjava","download_url":"https://codeload.github.com/litongjava/java-openai/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244752362,"owners_count":20504256,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-27T11:37:19.485Z","updated_at":"2025-03-21T07:16:14.860Z","avatar_url":"https://github.com/litongjava.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Java OpenAI Client\n\n## Introduction\n\n**Java OpenAI** is a robust client library for integrating OpenAI services into Java applications. Built on top of [OkHttp](https://square.github.io/okhttp/) and [FastJSON](https://github.com/alibaba/fastjson), it provides a seamless, efficient way to interact with OpenAI's APIs—enabling features such as chat completions, image processing, embeddings, and more. In addition to OpenAI, the library supports integration with Gemini, Jina, Textin, DeepSeek, and other services.\n\n## Table of Contents\n\n- [Java OpenAI Client](#java-openai-client)\n  - [Introduction](#introduction)\n  - [Table of Contents](#table-of-contents)\n  - [Features](#features)\n  - [Getting Started](#getting-started)\n    - [1. Add Dependencies](#1-add-dependencies)\n    - [2. Configure API Key](#2-configure-api-key)\n    - [3. Run With PromptEngine](#3-run-with-promptengine)\n    - [4. Run a Simple Test](#4-run-a-simple-test)\n    - [5. Another Simplified Example Using Roles](#5-another-simplified-example-using-roles)\n  - [Examples](#examples)\n    - [Chat Example](#chat-example)\n    - [Ask with Image](#ask-with-image)\n    - [Chat with Image](#chat-with-image)\n    - [Ask with Tools](#ask-with-tools)\n    - [Whisper Transcription](#whisper-transcription)\n    - [Embedding](#embedding)\n      - [Example 1: Generate Embedding](#example-1-generate-embedding)\n      - [Example 2: Simple Embedding](#example-2-simple-embedding)\n    - [Llama Integration](#llama-integration)\n    - [Perplexity Integration](#perplexity-integration)\n    - [Jina Rerank](#jina-rerank)\n    - [Jina Search](#jina-search)\n    - [Parse Markdown Response](#parse-markdown-response)\n    - [GOOGLE GEMINI](#google-gemini)\n      - [GOOGLE GEMINI Text](#google-gemini-text)\n      - [Google GEMINI Images](#google-gemini-images)\n      - [GOOGLE GEMINI Function Call](#google-gemini-function-call)\n      - [Gemini Upload File](#gemini-upload-file)\n      - [Gemini Ask with PDF](#gemini-ask-with-pdf)\n      - [Gemini OpenAI](#gemini-openai)\n    - [deepseek-openai](#deepseek-openai)\n    - [SiliconFlow DeepSeek](#siliconflow-deepseek)\n    - [SiliconFlow DeepSeek Image](#siliconflow-deepseek-image)\n  - [Additional Integrations](#additional-integrations)\n    - [VOLCENGINE: DEEPSEEK](#volcengine-deepseek)\n    - [Groq Integration](#groq-integration)\n      - [GroqSpeechClientTest](#groqspeechclienttest)\n    - [ApiFy](#apify)\n      - [LinkedIn Profile Scraper](#linkedin-profile-scraper)\n    - [SearchAPI](#searchapi)\n      - [Google Search](#google-search)\n    - [Supadata.ai](#supadataai)\n      - [YouTube Subtitle](#youtube-subtitle)\n  - [License](#license)\n\n## Features\n\n- **Chat Completions**: Interact effortlessly with OpenAI's chat models.\n- **Image Processing**: Convert images to text or other formats.\n- **Embeddings**: Generate text embeddings for various applications.\n- **Tool Integration**: Enhance functionality by integrating with external tools.\n- **Support for Additional Models**: Includes support for Llama, Perplexity, Gemini, Jina, DeepSeek, SiliconFlow, VOLCENGINE, Groq, ApiFy, SearchAPI, and Supadata.ai.\n- **Whisper Transcriptions**: Transcribe audio using Whisper.\n- **Easy Configuration**: Simplified setup using configuration files.\n\n## Getting Started\n\n### 1. Add Dependencies\n\nAdd the following dependencies to your `pom.xml`:\n\n```xml\n\u003cdependencies\u003e\n  \u003cdependency\u003e\n    \u003cgroupId\u003ecom.litongjava\u003c/groupId\u003e\n    \u003cartifactId\u003ejava-openai\u003c/artifactId\u003e\n    \u003cversion\u003e1.1.4\u003c/version\u003e\n  \u003c/dependency\u003e\n  \u003cdependency\u003e\n    \u003cgroupId\u003ecom.alibaba.fastjson2\u003c/groupId\u003e\n    \u003cartifactId\u003efastjson2\u003c/artifactId\u003e\n    \u003cversion\u003e2.0.52\u003c/version\u003e\n  \u003c/dependency\u003e\n\u003c/dependencies\u003e\n```\n\n### 2. Configure API Key\n\nCreate or update `src/main/resources/app.properties`:\n\n```properties\nOPENAI_API_KEY=your_openai_api_key_here\n```\n\nOther service keys (if applicable) should be added similarly (e.g., `GEMINI_API_KEY`, `DEEPSEEK_API_KEY`, `LLAMA_API_KEY`, etc.).\n\n### 3. Run With PromptEngine\n\n```java\npackage com.litongjava.prompt;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport com.litongjava.openai.chat.ChatResponseFormatType;\nimport com.litongjava.openai.chat.OpenAiChatMessage;\nimport com.litongjava.openai.chat.OpenAiChatRequestVo;\nimport com.litongjava.openai.chat.OpenAiChatResponseVo;\nimport com.litongjava.openai.client.OpenAiClient;\nimport com.litongjava.openai.constants.OpenAiModels;\nimport com.litongjava.template.PromptEngine;\nimport com.litongjava.tio.utils.environment.EnvUtils;\nimport com.litongjava.tio.utils.json.JsonUtils;\n\npublic class ProfessorEmojisTest {\n  public static void main(String[] args) {\n    // Load OPENAI_API_KEY from configuration\n    EnvUtils.load();\n\n    // Create messages\n    List\u003cOpenAiChatMessage\u003e messages = new ArrayList\u003c\u003e();\n    String prompt = PromptEngine.renderToString(\"professor_emojis_introduction_weaknesses_strengths_prompt.txt\");\n    String example = PromptEngine.renderToString(\"professor_emojis_introduction_weaknesses_strengths_prompt_example.txt\");\n    messages.add(new OpenAiChatMessage(\"system\", prompt));\n    messages.add(new OpenAiChatMessage(\"user\", example));\n\n    // Create chat request\n    OpenAiChatRequestVo chatRequestVo = new OpenAiChatRequestVo();\n    chatRequestVo.setStream(false);\n    chatRequestVo.setModel(OpenAiModels.GPT_4O_MINI);\n    chatRequestVo.setMessages(messages);\n\n    chatRequestVo\n        .setTemperature(0f)\n        .setTop_p(1.0f)\n        .setFrequency_penalty(0.0f)\n        .setPresence_penalty(0.0f)\n        .setResponse_format(ChatResponseFormatType.json_object);\n\n    String json = JsonUtils.toSkipNullJson(chatRequestVo);\n    System.out.println(\"Request JSON:\\n\" + json);\n\n    // Send HTTP request\n    OpenAiChatResponseVo chatCompletions = OpenAiClient.chatCompletions(chatRequestVo);\n    System.out.println(JsonUtils.toSkipNullJson(chatCompletions));\n  }\n}\n```\n\n**professor_emojis_introduction_weaknesses_strengths_prompt.txt**\n\n```txt\n\u003cinstruction\u003e\n  You are tasked with generating a comprehensive analysis report of a professor based on data from RateMyProfessor. Follow these steps to complete the task:\n\n  1. Use the provided variables to fill in the required fields in the JSON format.\n  2. Analyze the professor's teaching style, classroom interaction, and personal charisma based on student reviews.\n  3. Ensure the tone is humorous, witty, yet objective throughout the report.\n  4. Populate the 'emojis' field with emojis that reflect the professor's personality and characteristics.\n  5. Write a concise and impactful introduction summarizing the professor's teaching style, academic background, or notable qualities.\n  6. Identify and list the professor's weaknesses using the specified format, ensuring each entry is on a new line with a key and description separated by a colon.\n  7. Identify and list the professor's strengths using the specified format, ensuring each entry is on a new line with a key and description separated by a colon.\n  8. Ensure the output is strictly in JSON format and does not contain any XML tags.\n\n  The output should look like this:\n  {\n    \"emojis\": [\"emoji1\", \"emoji_2\", ...],\n    \"introduction\": \"professor_introduction\",\n    \"weaknesses\": \"**Weakness_name_1**:weakness_description_1\\n**Weakness_name_2**:weakness_description_2\\n...\",\n    \"strengths\": \"**Strength_name_1**:strength_description_1\\n**Strength_name_2**:strength_description_2\\n...\"\n  }\n\u003c/instruction\u003e\n```\n\n**prompts/professor_emojis_introduction_weaknesses_strengths_prompt_example.txt**\n\n```json\n[\n  {\n    \"Quality\": 5.0,\n    \"Difficulty\": 1.0,\n    \"Course\": \"EGMT1510\",\n    \"Date\": \"Jan 31st, 2025\",\n    \"For Credit\": \"Yes\",\n    \"Attendance\": \"Not Mandatory\",\n    \"Would Take Again\": \"Yes\",\n    \"Grade\": \"A+\",\n    \"Textbook\": \"Yes\",\n    \"Review\": \"I had Professor Levenson for the London First Program, and he was genuinely the kindest and most caring professor I have ever had. He is incredibly engaged with his students, and will make the effort to have a personal relationship with anyone willing to talk to him. He is an incredibly reasonable grader, and his course is genuinely enjoyable.\",\n    \"Tags\": [\"Amazing lectures\", \"Caring\", \"Accessible outside class\", \"Helpful\"],\n    \"Thumbs Up\": 0,\n    \"Thumbs Down\": 0\n  },\n  {\n    \"Quality\": 5.0,\n    \"Difficulty\": 1.0,\n    \"Course\": \"LONDON\",\n    \"Date\": \"Jan 12th, 2025\",\n    \"For Credit\": \"Yes\",\n    \"Attendance\": \"Not Mandatory\",\n    \"Would Take Again\": \"Yes\",\n    \"Grade\": \"A\",\n    \"Textbook\": \"N/A\",\n    \"Review\": \"I had him for my first semester during London First and he was amazing.\",\n    \"Tags\": [\"Get ready to read\", \"Amazing lectures\", \"Hilarious\", \"Helpful\"],\n    \"Thumbs Up\": 0,\n    \"Thumbs Down\": 0\n  },\n  {\n    \"Quality\": 5.0,\n    \"Difficulty\": 2.0,\n    \"Course\": \"EGMT1510\",\n    \"Date\": \"May 28th, 2024\",\n    \"For Credit\": \"Yes\",\n    \"Attendance\": \"Mandatory\",\n    \"Would Take Again\": \"Yes\",\n    \"Grade\": \"A\",\n    \"Textbook\": \"N/A\",\n    \"Review\": \"Professor Levenson is one of the sweetest instructors I have ever had. He was in charge of the London First Program and was the instructor for my engagements, which were (contrary to most Engagements) very fun, as we traveled around the city and watched plays and films as a class. I loved the discussions he led and he was always available to chat.\",\n    \"Tags\": [\"Inspirational\", \"Respected\", \"Accessible outside class\", \"Helpful\"],\n    \"Thumbs Up\": 0,\n    \"Thumbs Down\": 0\n  },\n  {\n    \"Quality\": 5.0,\n    \"Difficulty\": 2.0,\n    \"Course\": \"ENGL3610\",\n    \"Date\": \"May 2nd, 2023\",\n    \"For Credit\": \"Yes\",\n    \"Attendance\": \"Not Mandatory\",\n    \"Would Take Again\": \"Yes\",\n    \"Grade\": \"A\",\n    \"Textbook\": \"N/A\",\n    \"Review\": \"Professor Levenson is a great lecturer, and I really enjoyed the course material! I feel like I've learned a lot.\",\n    \"Tags\": [\"Get ready to read\", \"Amazing lectures\", \"Helpful\"],\n    \"Thumbs Up\": 0,\n    \"Thumbs Down\": 0\n  },\n  {\n    \"Quality\": 5.0,\n    \"Difficulty\": 3.0,\n    \"Course\": \"EGMT1510\",\n    \"Date\": \"Sep 14th, 2020\",\n    \"For Credit\": \"Yes\",\n    \"Attendance\": \"Mandatory\",\n    \"Would Take Again\": \"Yes\",\n    \"Grade\": \"A\",\n    \"Textbook\": \"No\",\n    \"Review\": \"I did Global First, so I took Professor Levenson's class in London. It was a great experience, and much of the class involved taking field trips and discussing plays we saw. He was very engaging, and discussions were always interesting.\",\n    \"Tags\": [\"Participation matters\", \"Amazing lectures\", \"Caring\", \"Helpful\"],\n    \"Thumbs Up\": 0,\n    \"Thumbs Down\": 0\n  }\n]\n```\n\n### 4. Run a Simple Test\n\n```java\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport com.litongjava.openai.chat.OpenAiChatMessage;\nimport com.litongjava.openai.chat.OpenAiChatRequestVo;\nimport com.litongjava.openai.chat.OpenAiChatResponseVo;\nimport com.litongjava.openai.client.OpenAiClient;\nimport com.litongjava.openai.constants.OpenAiModels;\nimport com.litongjava.tio.utils.environment.EnvUtils;\nimport com.litongjava.tio.utils.json.JsonUtils;\n\nimport okhttp3.Response;\n\npublic class SimpleAskExample {\n  public static void main(String[] args) {\n    // Load OPENAI_API_KEY from configuration\n    EnvUtils.load();\n\n    // Create messages\n    List\u003cOpenAiChatMessage\u003e messages = new ArrayList\u003c\u003e();\n    messages.add(new OpenAiChatMessage(\"user\", \"How are you?\"));\n\n    // Create chat request\n    OpenAiChatRequestVo chatRequestVo = new OpenAiChatRequestVo();\n    chatRequestVo.setStream(false);\n    chatRequestVo.setModel(OpenAiModels.GPT_4O_MINI);\n    chatRequestVo.setMessages(messages);\n\n    String json = JsonUtils.toSkipNullJson(chatRequestVo);\n    System.out.println(\"Request JSON:\\n\" + json);\n\n    // Send HTTP request\n    try (Response response = OpenAiClient.chatCompletions(json)) {\n      if (response.isSuccessful()) {\n        String responseBody = response.body().string();\n        OpenAiChatResponseVo chatCompletions = JsonUtils.parse(responseBody, OpenAiChatResponseVo.class);\n        System.out.println(\"Response:\\n\" + JsonUtils.toJson(chatCompletions));\n      } else {\n        System.err.println(\"Request failed: \" + response);\n      }\n    } catch (IOException e) {\n      e.printStackTrace();\n    }\n  }\n}\n```\n\n### 5. Another Simplified Example Using Roles\n\n```java\npackage com.litongjava.openai.example;\n\nimport com.litongjava.openai.chat.ChatResponseVo;\nimport com.litongjava.openai.client.OpenAiClient;\nimport com.litongjava.tio.utils.environment.EnvUtils;\nimport com.litongjava.tio.utils.json.JsonUtils;\n\npublic class ChatCompletionsWithRoleExample {\n  public static void main(String[] args) {\n    // Load OPENAI_API_KEY from configuration\n    EnvUtils.load();\n    \n    // Make a chat completion request with a specific role\n    ChatResponseVo chatResponse = OpenAiClient.chatCompletionsWithRole(\"user\", \"How are you?\");\n    System.out.println(\"Response:\\n\" + JsonUtils.toJson(chatResponse));\n  }\n}\n```\n\n---\n\n## Examples\n\n### Chat Example\n\n```java\npackage com.litongjava.openai.example;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport com.litongjava.openai.chat.ChatMessage;\nimport com.litongjava.openai.chat.ChatResponseVo;\nimport com.litongjava.openai.chat.OpenAiChatRequestVo;\nimport com.litongjava.openai.client.OpenAiClient;\nimport com.litongjava.openai.constants.OpenAiModels;\nimport com.litongjava.tio.utils.environment.EnvUtils;\nimport com.litongjava.tio.utils.json.JsonUtils;\n\nimport okhttp3.Response;\n\npublic class SimpleAskExample {\n  public static void main(String[] args) {\n    // Load OPENAI_API_KEY from configuration\n    EnvUtils.load();\n\n    // Create messages\n    List\u003cChatMessage\u003e messages = new ArrayList\u003c\u003e();\n    ChatMessage message = new ChatMessage().role(\"user\").content(\"How are you?\");\n    messages.add(message);\n\n    // Create chat request\n    OpenAiChatRequestVo chatRequestVo = new OpenAiChatRequestVo();\n    chatRequestVo.setStream(false);\n    chatRequestVo.setModel(OpenAiModels.GPT_4O_MINI);\n    chatRequestVo.setMessages(messages);\n\n    String json = JsonUtils.toJson(chatRequestVo);\n    System.out.println(\"Request JSON:\\n\" + json);\n\n    // Send HTTP request\n    try (Response response = OpenAiClient.chatCompletions(json)) {\n      if (response.isSuccessful()) {\n        String responseBody = response.body().string();\n        ChatResponseVo chatCompletions = JsonUtils.parse(responseBody, ChatResponseVo.class);\n        System.out.println(\"Response:\\n\" + JsonUtils.toJson(chatCompletions));\n      } else {\n        System.err.println(\"Request failed: \" + response);\n      }\n    } catch (IOException e) {\n      e.printStackTrace();\n    }\n  }\n}\n```\n\n### Ask with Image\n\n```java\npackage com.litongjava.perplexica.services;\n\nimport java.net.URL;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.junit.Test;\n\nimport com.litongjava.openai.chat.ChatMesageContent;\nimport com.litongjava.openai.chat.ChatRequestImage;\nimport com.litongjava.openai.chat.ChatResponseMessage;\nimport com.litongjava.openai.chat.OpenAiChatMessage;\nimport com.litongjava.openai.chat.OpenAiChatRequestVo;\nimport com.litongjava.openai.chat.OpenAiChatResponseVo;\nimport com.litongjava.openai.client.OpenAiClient;\nimport com.litongjava.openai.constants.OpenAiModels;\nimport com.litongjava.tio.utils.encoder.Base64Utils;\nimport com.litongjava.tio.utils.environment.EnvUtils;\nimport com.litongjava.tio.utils.http.ContentTypeUtils;\nimport com.litongjava.tio.utils.hutool.FileUtil;\nimport com.litongjava.tio.utils.hutool.FilenameUtils;\nimport com.litongjava.tio.utils.hutool.ResourceUtil;\nimport com.litongjava.tio.utils.json.JsonUtils;\n\npublic class AskWithImageOpenai {\n\n  @Test\n  public void imageToMarkDown() {\n    EnvUtils.load();\n    String apiKey = EnvUtils.getStr(\"OPENAI_API_KEY\");\n\n    String prompt = \"Convert the image to text and just output the text.\";\n\n    String filePath = \"images/200-dpi.png\";\n    URL url = ResourceUtil.getResource(filePath);\n    byte[] imageBytes = FileUtil.readUrlAsBytes(url);\n    String suffix = FilenameUtils.getSuffix(filePath);\n    String mimeType = ContentTypeUtils.getContentType(suffix);\n\n    String imageBase64 = Base64Utils.encodeImage(imageBytes, mimeType);\n\n    ChatRequestImage chatRequestImage = new ChatRequestImage();\n    chatRequestImage.setDetail(\"auto\");\n    chatRequestImage.setUrl(imageBase64);\n\n    List\u003cChatMesageContent\u003e multiContents = new ArrayList\u003c\u003e();\n    multiContents.add(new ChatMesageContent(prompt));\n    multiContents.add(new ChatMesageContent(chatRequestImage));\n\n    OpenAiChatMessage userMessage = new OpenAiChatMessage();\n    userMessage.role(\"user\").multiContents(multiContents);\n\n    List\u003cOpenAiChatMessage\u003e messages = new ArrayList\u003c\u003e();\n    messages.add(userMessage);\n\n    OpenAiChatRequestVo chatRequestVo = new OpenAiChatRequestVo();\n    chatRequestVo.setModel(OpenAiModels.GPT_4O_MINI);\n    chatRequestVo.setMessages(messages);\n    String json = JsonUtils.toSkipNullJson(chatRequestVo);\n    System.out.println(\"Request JSON:\\n\" + json);\n\n    OpenAiChatResponseVo chatResponse = OpenAiClient.chatCompletions(apiKey, chatRequestVo);\n    ChatResponseMessage responseMessage = chatResponse.getChoices().get(0).getMessage();\n    String content = responseMessage.getContent();\n    System.out.println(\"Response Content:\\n\" + content);\n  }\n}\n```\n\n### Chat with Image\n\n```java\npackage com.litongjava.maxkb.service;\n\nimport java.net.URL;\n\nimport org.junit.Test;\n\nimport com.litongjava.openai.chat.ChatResponseVo;\nimport com.litongjava.openai.client.OpenAiClient;\nimport com.litongjava.tio.utils.hutool.FileUtil;\nimport com.litongjava.tio.utils.hutool.FilenameUtils;\nimport com.litongjava.tio.utils.hutool.ResourceUtil;\n\npublic class DatasetDocumentSplitServiceTest {\n\n  @Test\n  public void chatWithImage() {\n    String apiKey = \"sk-your_openai_api_key_here\";\n    String prompt = \"Convert the image to text and just output the text.\";\n\n    String filePath = \"images/200-dpi.png\";\n    URL url = ResourceUtil.getResource(filePath);\n    byte[] imageBytes = FileUtil.readUrlAsBytes(url);\n    String suffix = FilenameUtils.getSuffix(filePath);\n\n    ChatResponseVo chatResponse = OpenAiClient.chatWithImage(apiKey, prompt, imageBytes, suffix);\n    String content = chatResponse.getChoices().get(0).getMessage().getContent();\n    System.out.println(\"Response Content:\\n\" + content);\n  }\n}\n```\n\n### Ask with Tools\n\n```java\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport com.litongjava.openai.chat.ChatMessage;\nimport com.litongjava.openai.chat.ChatRequestFunctionParameter;\nimport com.litongjava.openai.chat.ChatRequestFunctionProperty;\nimport com.litongjava.openai.chat.ChatRequestTool;\nimport com.litongjava.openai.chat.ChatRequestToolCallFunction;\nimport com.litongjava.openai.chat.ChatRequestVo;\nimport com.litongjava.openai.chat.ChatResponseVo;\nimport com.litongjava.openai.client.OpenAiClient;\nimport com.litongjava.tio.utils.environment.EnvUtils;\nimport com.litongjava.tio.utils.json.JsonUtils;\n\nimport okhttp3.Response;\n\npublic class AskWithTools {\n\n  public static void main(String[] args) {\n    // Load configuration\n    EnvUtils.load();\n    List\u003cChatMessage\u003e messages = new ArrayList\u003c\u003e();\n\n    messages.add(new ChatMessage()\n        .role(\"system\")\n        .content(\"You are an excellent student advisor. You can query the database. The database is PostgreSQL.\"));\n    messages.add(new ChatMessage()\n        .role(\"system\")\n        .content(\"How many tables are in my database?\"));\n\n    // Define function parameters\n    ChatRequestFunctionParameter parameter = new ChatRequestFunctionParameter();\n    parameter.setType(\"object\");\n    Map\u003cString, ChatRequestFunctionProperty\u003e properties = new HashMap\u003c\u003e();\n    properties.put(\"sql\", new ChatRequestFunctionProperty(\"string\", \"The SQL statement to execute.\"));\n    parameter.setProperties(properties);\n\n    List\u003cString\u003e required = new ArrayList\u003c\u003e();\n    required.add(\"sql\");\n    parameter.setRequired(required);\n\n    // Define the function\n    ChatRequestToolCallFunction function = new ChatRequestToolCallFunction();\n    function.setName(\"find\");\n    function.setDescription(\"Execute SQL query on the database.\");\n    function.setParameters(parameter);\n\n    // Define the tool\n    ChatRequestTool tool = new ChatRequestTool();\n    tool.setType(\"function\");\n    tool.setFunction(function);\n    List\u003cChatRequestTool\u003e tools = new ArrayList\u003c\u003e();\n    tools.add(tool);\n\n    // Create chat request\n    ChatRequestVo chatRequestVo = new ChatRequestVo();\n    chatRequestVo.setStream(false);\n    chatRequestVo.setModel(\"gpt-4o-2024-05-13\");\n    chatRequestVo.setMessages(messages);\n    chatRequestVo.setTools(tools);\n\n    String json = JsonUtils.toJson(chatRequestVo);\n    System.out.println(\"Request JSON:\\n\" + json);\n\n    // Send HTTP request\n    try (Response response = OpenAiClient.chatCompletions(json)) {\n      if (response.isSuccessful()) {\n        String responseBody = response.body().string();\n        System.out.println(\"Response:\\n\" + responseBody);\n        ChatResponseVo chatResponse = JsonUtils.parse(responseBody, ChatResponseVo.class);\n        System.out.println(\"Parsed Response:\\n\" + JsonUtils.toJson(chatResponse));\n      } else {\n        System.err.println(\"Request failed: \" + response);\n      }\n    } catch (IOException e) {\n      e.printStackTrace();\n    }\n  }\n}\n```\n\n### Whisper Transcription\n\n```java\npackage com.litongjava.client;\n\nimport java.io.File;\n\nimport org.junit.Test;\n\nimport com.litongjava.model.http.response.ResponseVo;\nimport com.litongjava.openai.whisper.WhisperClient;\nimport com.litongjava.openai.whisper.WhisperResponseFormat;\nimport com.litongjava.tio.utils.environment.EnvUtils;\n\npublic class WhisperClientTest {\n  @Test\n  public void transcriptions() {\n    EnvUtils.load();\n    String filename = \"path/to/your/audio.mp3\";\n    File file = new File(filename);\n    ResponseVo responseVo = WhisperClient.transcriptions(file, WhisperResponseFormat.srt);\n    System.out.println(responseVo.getBodyString());\n  }\n}\n```\n\n### Embedding\n\n#### Example 1: Generate Embedding\n\n```java\npackage com.litongjava.openai.example;\n\nimport java.io.IOException;\n\nimport com.litongjava.openai.client.OpenAiClient;\nimport com.litongjava.openai.embedding.EmbeddingRequestVo;\nimport com.litongjava.openai.embedding.EmbeddingResponseVo;\nimport com.litongjava.tio.utils.environment.EnvUtils;\nimport com.litongjava.tio.utils.json.JsonUtils;\n\nimport okhttp3.Response;\n\npublic class EmbeddingExample {\n\n  public static void main(String[] args) {\n    // Load configuration\n    EnvUtils.load();\n    \n    // Create embedding request\n    EmbeddingRequestVo embeddingRequest = new EmbeddingRequestVo();\n    embeddingRequest.setInput(\"What's your name?\");\n    embeddingRequest.setModel(\"text-embedding-3-small\");\n\n    String requestBody = JsonUtils.toJson(embeddingRequest);\n    System.out.println(\"Request JSON:\\n\" + requestBody);\n\n    // Send HTTP request\n    try (Response response = OpenAiClient.embeddings(requestBody)) {\n      if (response.isSuccessful()) {\n        String responseBody = response.body().string();\n        System.out.println(\"Response:\\n\" + responseBody);\n        \n        // Parse response\n        EmbeddingResponseVo responseVo = JsonUtils.parse(responseBody, EmbeddingResponseVo.class);\n        System.out.println(\"Parsed Response:\\n\" + JsonUtils.toJson(responseVo));\n      } else {\n        System.err.println(\"Request failed: \" + response);\n      }\n    } catch (IOException e) {\n      e.printStackTrace();\n    }\n  }\n}\n```\n\n#### Example 2: Simple Embedding\n\n```java\npackage com.litongjava.example;\n\nimport org.junit.Test;\n\nimport com.litongjava.openai.client.OpenAiClient;\nimport com.litongjava.openai.constants.OpenAiModels;\nimport com.litongjava.tio.utils.environment.EnvUtils;\n\npublic class SimpleEmbeddingExample {\n\n  @Test\n  public void embedding() {\n    // Load configuration\n    EnvUtils.load();\n    \n    String text = \"Hi\";\n    float[] embeddingArray = OpenAiClient.embeddingArray(text, OpenAiModels.TEXT_EMBEDDING_3_LARGE);\n    \n    System.out.println(\"Embedding Length: \" + embeddingArray.length);\n    // Expected output: 3072\n  }\n}\n```\n\n### Llama Integration\n\n```java\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.junit.Test;\n\nimport com.litongjava.openai.chat.ChatMessage;\nimport com.litongjava.openai.chat.ChatResponseVo;\nimport com.litongjava.openai.chat.OpenAiChatRequestVo;\nimport com.litongjava.openai.client.OpenAiClient;\nimport com.litongjava.openai.constants.LlamaConstants;\nimport com.litongjava.openai.constants.LlamaModels;\nimport com.litongjava.tio.utils.environment.EnvUtils;\n\npublic class Llama3_1_Test {\n\n  @Test\n  public void testLlamaChat() {\n    // Load configuration\n    EnvUtils.load();\n    \n    // Create messages\n    List\u003cChatMessage\u003e messages = new ArrayList\u003c\u003e();\n    messages.add(new ChatMessage(\"user\", \"How are you?\"));\n\n    // Create chat request\n    OpenAiChatRequestVo chatRequestVo = new OpenAiChatRequestVo()\n        .setModel(LlamaModels.LLAMA3_1_8B)\n        .setMessages(messages)\n        .setMaxTokens(3000);\n\n    String apiKey = EnvUtils.get(\"LLAMA_API_KEY\");\n\n    // Send HTTP request to Llama server\n    ChatResponseVo chatResponse = OpenAiClient.chatCompletions(LlamaConstants.SERVER_URL, apiKey, chatRequestVo);\n    String content = chatResponse.getChoices().get(0).getMessage().getContent();\n    System.out.println(\"Response Content:\\n\" + content);\n  }\n}\n```\n\n### Perplexity Integration\n\n```java\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.junit.Test;\n\nimport com.litongjava.openai.chat.ChatMessage;\nimport com.litongjava.openai.chat.ChatResponseVo;\nimport com.litongjava.openai.chat.OpenAiChatRequestVo;\nimport com.litongjava.openai.client.OpenAiClient;\nimport com.litongjava.openai.constants.PerplexityConstants;\nimport com.litongjava.openai.constants.PerplexityModels;\nimport com.litongjava.tio.utils.environment.EnvUtils;\n\npublic class PerplexityTest {\n\n  @Test\n  public void testPerplexityChat() {\n    // Load configuration\n    EnvUtils.load();\n    \n    // Create messages\n    List\u003cChatMessage\u003e messages = new ArrayList\u003c\u003e();\n    messages.add(new ChatMessage(\"user\", \"How are you?\"));\n\n    // Create chat request\n    OpenAiChatRequestVo chatRequestVo = new OpenAiChatRequestVo()\n        .setModel(PerplexityModels.LLAMA_3_1_SONAR_SMALL_128K_ONLINE)\n        .setMessages(messages)\n        .setMaxTokens(3000);\n\n    String apiKey = EnvUtils.get(\"PERPLEXITY_API_KEY\");\n\n    // Send HTTP request to Perplexity server\n    ChatResponseVo chatResponse = OpenAiClient.chatCompletions(PerplexityConstants.SERVER_URL, apiKey, chatRequestVo);\n    String content = chatResponse.getChoices().get(0).getMessage().getContent();\n    System.out.println(\"Response Content:\\n\" + content);\n  }\n}\n```\n\n### Jina Rerank\n\n```java\npackage com.litongjava.open.chat.client;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.junit.Test;\n\nimport com.litongjava.jian.rerank.JinaModel;\nimport com.litongjava.jian.rerank.JinaRerankClient;\nimport com.litongjava.jian.rerank.RerankReqVo;\nimport com.litongjava.jian.rerank.RerankRespVo;\nimport com.litongjava.tio.utils.environment.EnvUtils;\nimport com.litongjava.tio.utils.json.JsonUtils;\n\npublic class JinaRerankClientTest {\n\n  @Test\n  public void testRerank() {\n    // Load configuration\n    EnvUtils.load();\n    \n    // Prepare documents\n    List\u003cString\u003e documents = new ArrayList\u003c\u003e();\n    documents.add(\"Bio-Hautpflege für empfindliche Haut mit Aloe Vera und Kamille: ...\");\n    documents.add(\"Neue Make-up-Trends setzen auf kräftige Farben und innovative Techniken: ...\");\n    documents.add(\"Cuidado de la piel orgánico para piel sensible con aloe vera y manzanilla: ...\");\n    documents.add(\"Las nuevas tendencias de maquillaje se centran en colores vivos y técnicas innovadoras: ...\");\n    documents.add(\"Natural organic skincare products for sensitive skin: Experience the gentle care of aloe vera and chamomile extracts...\");\n    documents.add(\"New makeup trends focus on vivid colors and innovative techniques: A new era in the art of makeup...\");\n    documents.add(\"天然有機護膚產品，專為敏感肌設計：感受蘆薈與洋甘菊提取物的溫柔呵護...\");\n    documents.add(\"新しいメイクのトレンドは鮮やかな色と革新的な技術に焦点を当てています: ...\");\n\n    // Create rerank request\n    RerankReqVo reqVo = new RerankReqVo();\n    reqVo.setModel(JinaModel.JINA_RERANKER_V2_BASE_MULTILINGUAL);\n    reqVo.setQuery(\"Organic skincare products for sensitive skin\");\n    reqVo.setTopN(3);\n    reqVo.setDocuments(documents);\n\n    // Perform rerank\n    RerankRespVo respVo = JinaRerankClient.rerank(reqVo);\n    System.out.println(\"Rerank Response:\\n\" + JsonUtils.toJson(respVo));\n  }\n}\n```\n\n### Jina Search\n\n```java\nimport org.junit.Test;\n\nimport com.litongjava.jian.search.JinaSearchClient;\nimport com.litongjava.tio.utils.environment.EnvUtils;\n\npublic class JinaSearchServiceTest {\n\n  @Test\n  public void test() {\n    EnvUtils.load();\n    String result = JinaSearchClient.search(\"How can I run deepseek r1 with lama.cpp\");\n    System.out.println(result);\n  }\n}\n```\n\n### Parse Markdown Response\n\nA simple data class example:\n\n```java\npackage com.litongjava.searxng;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.experimental.Accessors;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@Accessors(chain = true)\npublic class WebPageContent {\n  private String title;\n  private String url;\n  private String description;\n  private String content;\n}\n```\n\nAnd a hypothetical parse method:\n\n```java\npublic static List\u003cWebPageContent\u003e parse(String markdown) {\n  // Implementation that parses a given markdown string\n  // to extract relevant fields (title, url, description, etc.)\n  // and returns a list of WebPageContent objects.\n}\n```\n\n### GOOGLE GEMINI\n#### GOOGLE GEMINI Text\n```java\npackage com.litongjava.gemini;\n\nimport java.util.Collections;\nimport java.util.List;\n\nimport com.litongjava.tio.utils.environment.EnvUtils;\n\n/**\n * Demo for Gemini\n */\npublic class GeminiDemo {\n\n  public static void main(String[] args) {\n    EnvUtils.load();\n    String googleApiKey = EnvUtils.getStr(\"GEMINI_API_KEY\");\n\n    // 1. Construct request body\n    GeminiPartVo part = new GeminiPartVo(\"Hello, how are you?\");\n    GeminiContentVo content = new GeminiContentVo(\"user\", Collections.singletonList(part));\n    GeminiChatRequestVo reqVo = new GeminiChatRequestVo(Collections.singletonList(content));\n\n    // 2. Send sync request: generateContent\n    GeminiChatResponseVo respVo = GeminiClient.generate(googleApiKey, GoogleGeminiModels.GEMINI_1_5_FLASH, reqVo);\n\n    if (respVo != null) {\n      List\u003cGeminiCandidateVo\u003e candidates = respVo.getCandidates();\n      GeminiCandidateVo candidate = candidates.get(0);\n      List\u003cGeminiPartVo\u003e parts = candidate.getContent().getParts();\n      if (candidate != null \u0026\u0026 candidate.getContent() != null \u0026\u0026 parts != null) {\n        String text = parts.get(0).getText();\n        System.out.println(\"Gemini answer text: \" + text);\n      }\n    }\n  }\n}\n```\n\n#### Google GEMINI Images\n\n```java\npackage com.litongjava.llm.service;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\nimport com.litongjava.gemini.GeminiCandidateVo;\nimport com.litongjava.gemini.GeminiChatRequestVo;\nimport com.litongjava.gemini.GeminiChatResponseVo;\nimport com.litongjava.gemini.GeminiClient;\nimport com.litongjava.gemini.GeminiContentVo;\nimport com.litongjava.gemini.GeminiInlineDataVo;\nimport com.litongjava.gemini.GeminiPartVo;\nimport com.litongjava.gemini.GoogleGeminiModels;\nimport com.litongjava.tio.utils.encoder.Base64Utils;\nimport com.litongjava.tio.utils.environment.EnvUtils;\nimport com.litongjava.tio.utils.http.ContentTypeUtils;\nimport com.litongjava.tio.utils.hutool.FilenameUtils;\n\npublic class LlmOcrService {\n\n  String prompt = \"Convert the image to text and just output the text.\";\n\n  public String parse(byte[] data, String filename) {\n\n    String suffix = FilenameUtils.getSuffix(filename);\n    String mimeType = ContentTypeUtils.getContentType(suffix);\n    String encodeImage = Base64Utils.encodeToString(data);\n    String googleApiKey = EnvUtils.getStr(\"GEMINI_API_KEY\");\n\n    // 1. Build request body\n    List\u003cGeminiPartVo\u003e parts = new ArrayList\u003c\u003e();\n    parts.add(new GeminiPartVo(prompt));\n    parts.add(new GeminiPartVo(new GeminiInlineDataVo(mimeType, encodeImage)));\n    GeminiContentVo content = new GeminiContentVo(\"user\", parts);\n    GeminiChatRequestVo reqVo = new GeminiChatRequestVo(Collections.singletonList(content));\n\n    // 2. Sync request: generateContent\n    GeminiChatResponseVo respVo = GeminiClient.generate(googleApiKey, GoogleGeminiModels.GEMINI_2_0_FLASH_EXP, reqVo);\n    if (respVo != null \u0026\u0026 respVo.getCandidates() != null) {\n      GeminiCandidateVo candidate = respVo.getCandidates().get(0);\n      if (candidate.getContent() != null \u0026\u0026 candidate.getContent().getParts() != null) {\n        GeminiPartVo partVo = candidate.getContent().getParts().get(0);\n        return partVo.getText();\n      }\n    }\n    return null;\n  }\n}\n```\n\n```java\npackage com.litongjava.llm.service;\n\nimport java.io.File;\n\nimport org.junit.Test;\n\nimport com.litongjava.jfinal.aop.Aop;\nimport com.litongjava.tio.utils.environment.EnvUtils;\nimport com.litongjava.tio.utils.hutool.FileUtil;\n\npublic class LlmOcrServiceTest {\n\n  @Test\n  public void test() {\n    EnvUtils.load();\n    String path = \"C:\\\\Users\\\\Administrator\\\\Pictures\\\\200-dpi.png\";\n    File file = new File(path);\n    byte[] bytes = FileUtil.readBytes(file);\n    String result = Aop.get(LlmOcrService.class).parse(bytes, file.getName());\n    System.out.println(result);\n  }\n}\n```\n\n#### GOOGLE GEMINI Function Call\n\n**Request Body JSON Example:**\n\n```json\n{\n  \"system_instruction\": {\n    \"parts\": {\n      \"text\": \"You are a helpful lighting system bot. You can turn lights on and off, and you can set the color. Do not perform any other tasks.\"\n    }\n  },\n  \"tools\": [\n    {\n      \"function_declarations\": [\n        {\n          \"name\": \"enable_lights\",\n          \"description\": \"Turn on the lighting system.\",\n          \"parameters\": {\n            \"type\": \"object\",\n            \"properties\": {\n              \"dummy\": {\n                \"type\": \"boolean\",\n                \"description\": \"A placeholder parameter.\"\n              }\n            },\n            \"required\": [\n              \"dummy\"\n            ]\n          }\n        },\n        {\n          \"name\": \"set_light_color\",\n          \"description\": \"Set the light color. Lights must be enabled for this to work.\",\n          \"parameters\": {\n            \"type\": \"object\",\n            \"properties\": {\n              \"rgb_hex\": {\n                \"type\": \"string\",\n                \"description\": \"The light color as a 6-digit hex string, e.g. ff0000 for red.\"\n              }\n            },\n            \"required\": [\n              \"rgb_hex\"\n            ]\n          }\n        },\n        {\n          \"name\": \"stop_lights\",\n          \"description\": \"Turn off the lighting system.\",\n          \"parameters\": {\n            \"type\": \"object\",\n            \"properties\": {\n              \"dummy\": {\n                \"type\": \"boolean\",\n                \"description\": \"A placeholder parameter.\"\n              }\n            },\n            \"required\": [\n              \"dummy\"\n            ]\n          }\n        }\n      ]\n    }\n  ],\n  \"tool_config\": {\n    \"function_calling_config\": {\n      \"mode\": \"ANY\",\n      \"allowed_function_names\": [\n        \"enable_lights\",\n        \"set_light_color\",\n        \"stop_lights\"\n      ]\n    }\n  },\n  \"contents\": {\n    \"role\": \"user\",\n    \"parts\": {\n      \"text\": \"Turn off the lighting system\"\n    }\n  }\n}\n```\n\n**Java Code:**\n\n```java\npackage com.litongjava.gemini;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport com.litongjava.tio.utils.environment.EnvUtils;\nimport com.litongjava.tio.utils.json.JsonUtils;\n\npublic class GeminiFunctionCallExample {\n\n  public static void main(String[] args) {\n    EnvUtils.load();\n\n    // 1. system_instruction\n    GeminiSystemInstructionVo systemInstruction = new GeminiSystemInstructionVo(\n        new GeminiPartVo(\"You are a helpful lighting system bot. You can turn lights on and off, and you can set the color. Do not perform any other tasks.\"));\n\n    // 2. tools -\u003e function_declarations\n    GeminiFunctionDeclarationVo enableLightsFunc = new GeminiFunctionDeclarationVo();\n    enableLightsFunc.setName(\"enable_lights\");\n    enableLightsFunc.setDescription(\"Turn on the lighting system.\");\n    Map\u003cString, Object\u003e enableLightsProperties = new HashMap\u003c\u003e();\n    enableLightsProperties.put(\"dummy\", new HashMap\u003cString, Object\u003e() {{\n      put(\"type\", \"boolean\");\n      put(\"description\", \"A placeholder parameter.\");\n    }});\n    Map\u003cString, Object\u003e enableLightsParams = new HashMap\u003c\u003e();\n    enableLightsParams.put(\"type\", \"object\");\n    enableLightsParams.put(\"properties\", enableLightsProperties);\n    enableLightsParams.put(\"required\", Arrays.asList(\"dummy\"));\n    enableLightsFunc.setParameters(enableLightsParams);\n\n    GeminiFunctionDeclarationVo setLightColorFunc = new GeminiFunctionDeclarationVo();\n    setLightColorFunc.setName(\"set_light_color\");\n    setLightColorFunc.setDescription(\"Set the light color. Lights must be enabled for this to work.\");\n    Map\u003cString, Object\u003e setLightColorProperties = new HashMap\u003c\u003e();\n    setLightColorProperties.put(\"rgb_hex\", new HashMap\u003cString, String\u003e() {{\n      put(\"type\", \"string\");\n      put(\"description\", \"The light color as a 6-digit hex string, e.g. ff0000 for red.\");\n    }});\n    Map\u003cString, Object\u003e setLightColorParams = new HashMap\u003c\u003e();\n    setLightColorParams.put(\"type\", \"object\");\n    setLightColorParams.put(\"properties\", setLightColorProperties);\n    setLightColorParams.put(\"required\", Arrays.asList(\"rgb_hex\"));\n    setLightColorFunc.setParameters(setLightColorParams);\n\n    GeminiFunctionDeclarationVo stopLightsFunc = new GeminiFunctionDeclarationVo();\n    stopLightsFunc.setName(\"stop_lights\");\n    stopLightsFunc.setDescription(\"Turn off the lighting system.\");\n    Map\u003cString, Object\u003e stopLightsProperties = new HashMap\u003c\u003e();\n    stopLightsProperties.put(\"dummy\", new HashMap\u003cString, Object\u003e() {{\n      put(\"type\", \"boolean\");\n      put(\"description\", \"A placeholder parameter.\");\n    }});\n    Map\u003cString, Object\u003e stopLightsParams = new HashMap\u003c\u003e();\n    stopLightsParams.put(\"type\", \"object\");\n    stopLightsParams.put(\"properties\", stopLightsProperties);\n    stopLightsParams.put(\"required\", Arrays.asList(\"dummy\"));\n    stopLightsFunc.setParameters(stopLightsParams);\n\n    // Single tool with multiple functions\n    GeminiToolVo tool = new GeminiToolVo(Arrays.asList(enableLightsFunc, setLightColorFunc, stopLightsFunc));\n\n    // 3. tool_config\n    GeminiFunctionCallingConfigVo funcCallingConfig = new GeminiFunctionCallingConfigVo();\n    funcCallingConfig.setMode(\"ANY\");\n    funcCallingConfig.setAllowed_function_names(Arrays.asList(\"enable_lights\", \"set_light_color\", \"stop_lights\"));\n\n    GeminiToolConfigVo toolConfig = new GeminiToolConfigVo(funcCallingConfig);\n\n    // 4. user message contents\n    GeminiPartVo userPart = new GeminiPartVo(\"Turn off the lighting system\");\n    GeminiContentVo userContent = new GeminiContentVo(\"user\", Arrays.asList(userPart));\n\n    // 5. Assemble request\n    GeminiChatRequestVo requestVo = new GeminiChatRequestVo();\n    requestVo.setSystem_instruction(systemInstruction);\n    requestVo.setTools(Arrays.asList(tool));\n    requestVo.setTool_config(toolConfig);\n    requestVo.setContents(Arrays.asList(userContent));\n\n    // Convert to JSON\n    String requestJson = JsonUtils.toJson(requestVo);\n    System.out.println(\"==== Request JSON ====\");\n    System.out.println(requestJson);\n\n    // 6. Send request\n    GeminiChatResponseVo response = GeminiClient.generate(\"gemini-1.5-flash\", requestVo);\n\n    // 7. Print response\n    if (response != null \u0026\u0026 response.getCandidates() != null) {\n      for (GeminiCandidateVo candidate : response.getCandidates()) {\n        GeminiContentResponseVo content = candidate.getContent();\n        if (content == null || content.getParts() == null) continue;\n        for (GeminiPartVo part : content.getParts()) {\n          if (part.getFunctionCall() != null) {\n            System.out.println(\"[Function Call Response]\");\n            System.out.println(\"Function Name: \" + part.getFunctionCall().getName());\n            System.out.println(\"Function Args: \" + part.getFunctionCall().getArgs());\n          } else {\n            System.out.println(\"[Text Response]\");\n            System.out.println(\"Model Text: \" + part.getText());\n          }\n        }\n      }\n    } else {\n      System.out.println(\"No response or no candidates from Gemini.\");\n    }\n  }\n}\n```\n\n#### Gemini Upload File\n\n```java\npackage com.litongjava.gemini;\n\nimport java.io.IOException;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\n\nimport com.litongjava.tio.utils.environment.EnvUtils;\nimport com.litongjava.tio.utils.json.JsonUtils;\n\npublic class GeminiClientUploadFileTest {\n  public static void main(String[] args) throws IOException {\n    EnvUtils.load();\n    Path path = Paths.get(\"C:\\\\Users\\\\Administrator\\\\Downloads\\\\Lab Equipments Activity Sheet.pdf\");\n    byte[] bytes = Files.readAllBytes(path);\n    FileUploadResponseVo responseVo = GeminiClient.uploadFile(bytes);\n    System.out.println(JsonUtils.toJson(responseVo));\n  }\n}\n```\n\n**Sample Response:**\n\n```json\n{\n  \"file\": {\n    \"name\": \"files/mo7v85d4zum5\",\n    \"mimeType\": \"application/pdf\",\n    \"sizeBytes\": \"295078\",\n    \"createTime\": \"2025-01-23T06:54:56.365928Z\",\n    \"updateTime\": \"2025-01-23T06:54:56.365928Z\",\n    \"expirationTime\": \"2025-01-25T06:54:56.347859648Z\",\n    \"sha256Hash\": \"...\",\n    \"uri\": \"https://generativelanguage.googleapis.com/v1beta/files/mo7v85d4zum5\",\n    \"state\": \"ACTIVE\",\n    \"source\": \"UPLOADED\"\n  }\n}\n```\n\n#### Gemini Ask with PDF\n\n```java\npackage com.litongjava.gemini;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\nimport com.litongjava.tio.utils.environment.EnvUtils;\n\npublic class GeminiClientAskWithPdfTest {\n\n  public static void main(String[] args) {\n    EnvUtils.load();\n    String googleApiKey = EnvUtils.getStr(\"GEMINI_API_KEY\");\n\n    // Suppose you have an uploaded PDF file\n    String mimeType = \"application/pdf\";\n    String fileUri = \"https://generativelanguage.googleapis.com/v1beta/files/4eqnhyuzvzkb\";\n\n    // 1. Construct request\n    List\u003cGeminiPartVo\u003e parts = new ArrayList\u003c\u003e();\n    parts.add(new GeminiPartVo(\"Translate to Chinese\"));\n    parts.add(new GeminiPartVo(new GeminiFileDataVo(mimeType, fileUri)));\n    GeminiContentVo content = new GeminiContentVo(\"user\", parts);\n    GeminiChatRequestVo reqVo = new GeminiChatRequestVo(Collections.singletonList(content));\n\n    // 2. Send sync request\n    GeminiChatResponseVo respVo = GeminiClient.generate(googleApiKey, GoogleGeminiModels.GEMINI_1_5_FLASH, reqVo);\n\n    // 3. Print response\n    if (respVo != null \u0026\u0026 respVo.getCandidates() != null) {\n      respVo.getCandidates().forEach(candidate -\u003e {\n        if (candidate.getContent() != null \u0026\u0026 candidate.getContent().getParts() != null) {\n          candidate.getContent().getParts().forEach(partVo -\u003e {\n            System.out.println(\"Gemini answer text: \" + partVo.getText());\n          });\n        }\n      });\n    }\n  }\n}\n```\n\n#### Gemini OpenAI\n\nIn your `app.properties` add:\n\n```properties\nOPENAI_API_KEY=\u003cGemini key here\u003e\nOPENAI_API_URL=https://generativelanguage.googleapis.com/v1beta/openai\n```\n\nThen in code:\n\n```java\npackage com.litongjava.perplexica.services;\n\nimport com.litongjava.gemini.GoogleGeminiModels;\nimport com.litongjava.openai.chat.OpenAiChatResponseVo;\nimport com.litongjava.openai.client.OpenAiClient;\nimport com.litongjava.tio.utils.environment.EnvUtils;\nimport com.litongjava.tio.utils.json.JsonUtils;\n\npublic class GeminiClientTest {\n  public static void main(String[] args) {\n    EnvUtils.load();\n    OpenAiChatResponseVo chatResponse = OpenAiClient.chatWithModel(\n        GoogleGeminiModels.GEMINI_2_0_FLASH_EXP,\n        \"user\",\n        \"How are you?\"\n    );\n    System.out.println(JsonUtils.toJson(chatResponse));\n  }\n}\n```\n\n### deepseek-openai\n\n```java\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport com.litongjava.deepseek.DeepSeekConst;\nimport com.litongjava.deepseek.DeepSeekModels;\nimport com.litongjava.openai.chat.OpenAiChatMessage;\nimport com.litongjava.openai.chat.OpenAiChatRequestVo;\nimport com.litongjava.openai.chat.OpenAiChatResponseVo;\nimport com.litongjava.openai.client.OpenAiClient;\nimport com.litongjava.tio.utils.environment.EnvUtils;\nimport com.litongjava.tio.utils.json.JsonUtils;\n\npublic class DeepSeekClientTest {\n\n  public static void main(String[] args) {\n    EnvUtils.load();\n    List\u003cOpenAiChatMessage\u003e messages = new ArrayList\u003c\u003e();\n    messages.add(new OpenAiChatMessage(\"user\", \"Hi\"));\n\n    OpenAiChatRequestVo chatRequestVo = new OpenAiChatRequestVo()\n        .setModel(DeepSeekModels.DEEPSEEK_REASONER)\n        .setMessages(messages)\n        .setMax_tokens(8000);\n\n    String apiKey = EnvUtils.getStr(\"DEEPSEEK_API_KEY\");\n    OpenAiChatResponseVo chatResponse = OpenAiClient.chatCompletions(DeepSeekConst.BASE_URL, apiKey, chatRequestVo);\n    System.out.println(JsonUtils.toSkipNullJson(chatResponse));\n  }\n}\n```\n\n### SiliconFlow DeepSeek\n\n```java\npackage com.litongjava.perplexica.services;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport com.litongjava.openai.chat.OpenAiChatMessage;\nimport com.litongjava.openai.chat.OpenAiChatRequestVo;\nimport com.litongjava.openai.chat.OpenAiChatResponseVo;\nimport com.litongjava.openai.client.OpenAiClient;\nimport com.litongjava.siliconflow.SiliconFlowConsts;\nimport com.litongjava.siliconflow.SiliconFlowModels;\nimport com.litongjava.tio.utils.environment.EnvUtils;\nimport com.litongjava.tio.utils.json.JsonUtils;\n\nimport okhttp3.Response;\n\npublic class SiliconFlowDeepSeekTest {\n  public static void main(String[] args) {\n    // Load OPENAI_API_KEY from configuration\n    EnvUtils.load();\n    String apiKey = EnvUtils.getStr(\"SILICONFLOW_API_KEY\");\n\n    // Create messages\n    List\u003cOpenAiChatMessage\u003e messages = new ArrayList\u003c\u003e();\n    messages.add(new OpenAiChatMessage(\"user\", \"How are you?\"));\n\n    // Create chat request\n    OpenAiChatRequestVo chatRequestVo = new OpenAiChatRequestVo();\n    chatRequestVo.setStream(false);\n    chatRequestVo.setModel(SiliconFlowModels.DEEPSEEK_R1);\n    chatRequestVo.setMessages(messages);\n\n    String json = JsonUtils.toSkipNullJson(chatRequestVo);\n    System.out.println(\"Request JSON:\\n\" + json);\n\n    // Send HTTP request\n    try (Response response = OpenAiClient.chatCompletions(SiliconFlowConsts.SELICONFLOW_API_BASE, apiKey, json)) {\n      if (response.isSuccessful()) {\n        String responseBody = response.body().string();\n        OpenAiChatResponseVo chatCompletions = JsonUtils.parse(responseBody, OpenAiChatResponseVo.class);\n        System.out.println(\"Response:\\n\" + JsonUtils.toSkipNullJson(chatCompletions));\n      } else {\n        System.err.println(\"Request failed: \" + response);\n      }\n    } catch (IOException e) {\n      e.printStackTrace();\n    }\n  }\n}\n```\n\n### SiliconFlow DeepSeek Image\n\n```java\npackage com.litongjava.perplexica.services;\n\nimport java.net.URL;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.junit.Test;\n\nimport com.litongjava.openai.chat.ChatMesageContent;\nimport com.litongjava.openai.chat.ChatRequestImage;\nimport com.litongjava.openai.chat.ChatResponseMessage;\nimport com.litongjava.openai.chat.OpenAiChatMessage;\nimport com.litongjava.openai.chat.OpenAiChatRequestVo;\nimport com.litongjava.openai.chat.OpenAiChatResponseVo;\nimport com.litongjava.openai.client.OpenAiClient;\nimport com.litongjava.siliconflow.SiliconFlowConsts;\nimport com.litongjava.siliconflow.SiliconFlowModels;\nimport com.litongjava.tio.utils.encoder.Base64Utils;\nimport com.litongjava.tio.utils.environment.EnvUtils;\nimport com.litongjava.tio.utils.http.ContentTypeUtils;\nimport com.litongjava.tio.utils.hutool.FileUtil;\nimport com.litongjava.tio.utils.hutool.FilenameUtils;\nimport com.litongjava.tio.utils.hutool.ResourceUtil;\nimport com.litongjava.tio.utils.json.JsonUtils;\n\npublic class AskWithImageDeepSeek {\n\n  @Test\n  public void imageToMarkDown() {\n    EnvUtils.load();\n    String apiKey = EnvUtils.getStr(\"SILICONFLOW_API_KEY\");\n\n    String prompt = \"Convert the image to text and just output the text.\";\n\n    String filePath = \"images/200-dpi.png\";\n    URL url = ResourceUtil.getResource(filePath);\n    byte[] imageBytes = FileUtil.readUrlAsBytes(url);\n    String suffix = FilenameUtils.getSuffix(filePath);\n    String mimeType = ContentTypeUtils.getContentType(suffix);\n\n    String imageBase64 = Base64Utils.encodeImage(imageBytes, mimeType);\n\n    ChatRequestImage chatRequestImage = new ChatRequestImage();\n    chatRequestImage.setUrl(imageBase64);\n\n    List\u003cChatMesageContent\u003e multiContents = new ArrayList\u003c\u003e();\n    multiContents.add(new ChatMesageContent(chatRequestImage));\n    multiContents.add(new ChatMesageContent(prompt));\n\n    OpenAiChatMessage userMessage = new OpenAiChatMessage();\n    userMessage.role(\"user\").multiContents(multiContents);\n\n    List\u003cOpenAiChatMessage\u003e messages = new ArrayList\u003c\u003e();\n    messages.add(userMessage);\n\n    OpenAiChatRequestVo chatRequestVo = new OpenAiChatRequestVo();\n    // DEEPSEEK_R1 is a text-only model, so use DEEPSEEK_VL2 for image processing\n    chatRequestVo.setModel(SiliconFlowModels.DEEPSEEK_VL2);\n    chatRequestVo.setMax_tokens(1024).setTemperature(0.7f).setTop_p(0.7f).setTop_k(50).setFrequency_penalty(0);\n    chatRequestVo.setMessages(messages);\n\n    OpenAiChatResponseVo chatResponse =\n        OpenAiClient.chatCompletions(SiliconFlowConsts.SELICONFLOW_API_BASE, apiKey, chatRequestVo);\n    ChatResponseMessage responseMessage = chatResponse.getChoices().get(0).getMessage();\n    String content = responseMessage.getContent();\n    System.out.println(\"Response Content:\\n\" + content);\n  }\n}\n```\n\n---\n\n## Additional Integrations\n\n### VOLCENGINE: DEEPSEEK\n\n```java\npackage llm;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport com.litongjava.openai.chat.OpenAiChatMessage;\nimport com.litongjava.openai.chat.OpenAiChatRequestVo;\nimport com.litongjava.openai.chat.OpenAiChatResponseVo;\nimport com.litongjava.openai.client.OpenAiClient;\nimport com.litongjava.tio.utils.environment.EnvUtils;\nimport com.litongjava.tio.utils.json.JsonUtils;\nimport com.litongjava.volcengine.VolcEngineConst;\nimport com.litongjava.volcengine.VolcEngineModels;\n\npublic class VolcEngineDeepSeekClient {\n  public static void main(String[] args) {\n    EnvUtils.load();\n    String apiKey = EnvUtils.get(\"VOLCENGINE_API_KEY\");\n\n    List\u003cOpenAiChatMessage\u003e messages = new ArrayList\u003c\u003e();\n    messages.add(new OpenAiChatMessage(\"system\", \"You are an AI assistant.\"));\n    messages.add(new OpenAiChatMessage(\"user\", \"What are the common cruciferous vegetables?\"));\n\n    OpenAiChatRequestVo chatRequest = new OpenAiChatRequestVo();\n    chatRequest.setModel(VolcEngineModels.DEEPSEEK_V3_241226);\n    chatRequest.setMessages(messages);\n\n    OpenAiChatResponseVo chatResponse = OpenAiClient.chatCompletions(VolcEngineConst.BASE_URL, apiKey, chatRequest);\n    System.out.println(JsonUtils.toSkipNullJson(chatResponse));\n  }\n}\n```\n\n### Groq Integration\n\n#### GroqSpeechClientTest\n\n```java\npackage com.litongjava.groq;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.nio.file.Files;\n\nimport org.junit.Test;\n\nimport com.litongjava.tio.utils.environment.EnvUtils;\nimport com.litongjava.tio.utils.json.JsonUtils;\n\npublic class GroqSpeechClientTest {\n\n  @Test\n  public void test() {\n    EnvUtils.load();\n    String filePath = \"recording_1739969996898.wav\";\n    String model = \"whisper-large-v3\";\n    String fileName = new File(filePath).getName();\n\n    TranscriptionsRequest reqVo = new TranscriptionsRequest();\n    reqVo.setModel(model).setLanguage(\"zh-cn\");\n    byte[] audioData = null;\n    try {\n      audioData = Files.readAllBytes(new File(filePath).toPath());\n      TranscriptionsResponse transcriptions = GroqSpeechClient.transcriptions(audioData, fileName, reqVo);\n      System.out.println(JsonUtils.toJson(transcriptions));\n    } catch (IOException e) {\n      e.printStackTrace();\n    }\n  }\n}\n```\n\n### ApiFy\n\n#### LinkedIn Profile Scraper\n\n```java\npackage com.litongjava.client;\n\nimport org.junit.Test;\n\nimport com.litongjava.apify.ApiFyClient;\nimport com.litongjava.apify.ApiFyLinkedProfileReqVo;\nimport com.litongjava.model.http.response.ResponseVo;\nimport com.litongjava.tio.utils.environment.EnvUtils;\n\npublic class ApiFyClientTest {\n\n  @Test\n  public void testLinkedIn() {\n    // Load APIFY_API_KEY\n    EnvUtils.load();\n    ApiFyLinkedProfileReqVo reqVo = new ApiFyLinkedProfileReqVo(\"https://www.linkedin.com/in/nicolaushilleary\");\n    ResponseVo response = ApiFyClient.linkedinProfileScraper(reqVo);\n    System.out.println(response.getBodyString());\n  }\n}\n```\n\n### SearchAPI\n\n#### Google Search\n\n```java\npackage com.litongjava.client;\n\nimport org.junit.Test;\n\nimport com.litongjava.model.http.response.ResponseVo;\nimport com.litongjava.searchapi.SearchapiClient;\nimport com.litongjava.searchapi.SearchapiResult;\nimport com.litongjava.tio.utils.environment.EnvUtils;\nimport com.litongjava.tio.utils.json.FastJson2Utils;\n\npublic class SearchapiClientTest {\n  @Test\n  public void search() {\n    // SEARCHAPI_API_KEY\n    EnvUtils.load();\n    ResponseVo responseVo = SearchapiClient.search(\"KaiZhao at SJSU\");\n    String bodyString = responseVo.getBodyString();\n    if (responseVo.isOk()) {\n      SearchapiResult result = FastJson2Utils.parse(bodyString, SearchapiResult.class);\n      System.out.println(result);\n    } else {\n      System.out.println(bodyString);\n    }\n  }\n}\n```\n\n### Supadata.ai\n\n#### YouTube Subtitle\n\n```java\npackage com.litongjava.client;\n\nimport java.util.List;\n\nimport org.junit.Test;\n\nimport com.litongjava.supadata.SubTitleContent;\nimport com.litongjava.supadata.SubTitleResponse;\nimport com.litongjava.supadata.SupadataClient;\nimport com.litongjava.tio.utils.environment.EnvUtils;\nimport com.litongjava.tio.utils.video.VideoTimeUtils;\n\npublic class SupadataClientTest {\n\n  @Test\n  public void getSubtitleTest() {\n    // Example: You can use a YouTube video id\n    String id = \"31FpW6CMmYE\";\n    // Load SUPADATA_API_KEY\n    EnvUtils.load();\n    SubTitleResponse subTitle = SupadataClient.getSubTitle(id);\n    List\u003cSubTitleContent\u003e content = subTitle.getContent();\n    StringBuffer stringBuffer = new StringBuffer();\n    for (SubTitleContent subTitleContent : content) {\n      long offset = subTitleContent.getOffset();\n      long duration = subTitleContent.getDuration();\n      // Calculate end time = start time + duration\n      long endTime = offset + duration;\n      String startStr = VideoTimeUtils.formatTime(offset);\n      String endStr = VideoTimeUtils.formatTime(endTime);\n      String text = subTitleContent.getText();\n      stringBuffer.append(startStr).append(\"-\").append(endStr).append(\" \").append(text).append(\"\\r\\n\");\n    }\n    System.out.println(stringBuffer.toString());\n  }\n}\n```\n\n---\n\n## License\n\nThis project is licensed under the [MIT License](LICENSE). Feel free to contribute, report issues, or submit pull requests for improvements.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flitongjava%2Fjava-openai","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flitongjava%2Fjava-openai","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flitongjava%2Fjava-openai/lists"}