Created
May 15, 2025 23:59
-
-
Save Lycolia/bb72749c708f2781b58c14a817a81862 to your computer and use it in GitHub Desktop.
Open WebUI Gemini Manifold Pipe
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| title: Gemini Manifold Pipe | |
| author: justinh-rahb | |
| author_url: https://github.com/justinh-rahb | |
| funding_url: https://github.com/open-webui | |
| version: 0.1.4 | |
| license: MIT | |
| """ | |
| import os | |
| import json | |
| import re | |
| from pydantic import BaseModel, Field | |
| import google.generativeai as genai | |
| from google.generativeai.types import GenerationConfig, GenerateContentResponse | |
| from typing import List, Union, Iterator | |
| # Set DEBUG to True to enable detailed logging | |
| DEBUG = False | |
| class Pipe: | |
| class Valves(BaseModel): | |
| GOOGLE_API_KEY: str = Field(default="") | |
| USE_PERMISSIVE_SAFETY: bool = Field(default=False) | |
| def __init__(self): | |
| self.id = "google_genai" | |
| self.type = "manifold" | |
| self.name = "Google: " | |
| self.valves = self.Valves( | |
| **{ | |
| "GOOGLE_API_KEY": os.getenv("GOOGLE_API_KEY", ""), | |
| "USE_PERMISSIVE_SAFETY": False, | |
| } | |
| ) | |
| def get_google_models(self): | |
| if not self.valves.GOOGLE_API_KEY: | |
| return [ | |
| { | |
| "id": "error", | |
| "name": "GOOGLE_API_KEY is not set. Please update the API Key in the valves.", | |
| } | |
| ] | |
| try: | |
| genai.configure(api_key=self.valves.GOOGLE_API_KEY) | |
| models = genai.list_models() | |
| return [ | |
| { | |
| "id": model.name[7:], # remove the "models/" part | |
| "name": model.display_name, | |
| } | |
| for model in models | |
| if "generateContent" in model.supported_generation_methods | |
| if model.name.startswith("models/") | |
| ] | |
| except Exception as e: | |
| if DEBUG: | |
| print(f"Error fetching Google models: {e}") | |
| return [ | |
| {"id": "error", "name": f"Could not fetch models from Google: {str(e)}"} | |
| ] | |
| def pipes(self) -> List[dict]: | |
| return self.get_google_models() | |
| def pipe(self, body: dict) -> Union[str, Iterator[str]]: | |
| if not self.valves.GOOGLE_API_KEY: | |
| return "Error: GOOGLE_API_KEY is not set" | |
| try: | |
| genai.configure(api_key=self.valves.GOOGLE_API_KEY) | |
| model_id = body["model"] | |
| if model_id.startswith("google_genai."): | |
| model_id = model_id[12:] | |
| model_id = re.sub(r"^[^\.]+?\.", "", model_id) | |
| if not model_id.startswith("gemini-"): | |
| return f"Error: Invalid model name format: {model_id}" | |
| messages = body["messages"] | |
| stream = body.get("stream", False) | |
| if DEBUG: | |
| print("Incoming body:", str(body)) | |
| system_message = next( | |
| (msg["content"] for msg in messages if msg["role"] == "system"), None | |
| ) | |
| contents = [] | |
| for message in messages: | |
| if message["role"] != "system": | |
| if isinstance(message.get("content"), list): | |
| parts = [] | |
| for content in message["content"]: | |
| if content["type"] == "text": | |
| parts.append({"text": content["text"]}) | |
| elif content["type"] == "image_url": | |
| image_url = content["image_url"]["url"] | |
| if image_url.startswith("data:image"): | |
| image_data = image_url.split(",")[1] | |
| parts.append( | |
| { | |
| "inline_data": { | |
| "mime_type": "image/jpeg", | |
| "data": image_data, | |
| } | |
| } | |
| ) | |
| else: | |
| parts.append({"image_url": image_url}) | |
| contents.append({"role": message["role"], "parts": parts}) | |
| else: | |
| contents.append( | |
| { | |
| "role": ( | |
| "user" if message["role"] == "user" else "model" | |
| ), | |
| "parts": [{"text": message["content"]}], | |
| } | |
| ) | |
| if system_message: | |
| contents.insert( | |
| 0, | |
| {"role": "user", "parts": [{"text": f"System: {system_message}"}]}, | |
| ) | |
| if "gemini-1.5" in model_id: | |
| model = genai.GenerativeModel( | |
| model_name=model_id, system_instruction=system_message | |
| ) | |
| else: | |
| model = genai.GenerativeModel(model_name=model_id) | |
| generation_config = GenerationConfig( | |
| temperature=body.get("temperature", 0.7), | |
| top_p=body.get("top_p", 0.9), | |
| top_k=body.get("top_k", 40), | |
| max_output_tokens=body.get("max_tokens", 8192), | |
| stop_sequences=body.get("stop", []), | |
| ) | |
| # Safety settings omitted for brevity... | |
| if self.valves.USE_PERMISSIVE_SAFETY: | |
| safety_settings = { | |
| genai.types.HarmCategory.HARM_CATEGORY_HARASSMENT: genai.types.HarmBlockThreshold.BLOCK_NONE, | |
| genai.types.HarmCategory.HARM_CATEGORY_HATE_SPEECH: genai.types.HarmBlockThreshold.BLOCK_NONE, | |
| genai.types.HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: genai.types.HarmBlockThreshold.BLOCK_NONE, | |
| genai.types.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: genai.types.HarmBlockThreshold.BLOCK_NONE, | |
| } | |
| else: | |
| safety_settings = body.get("safety_settings") | |
| if DEBUG: | |
| print("Google API request:") | |
| print(" Model:", model_id) | |
| print(" Contents:", str(contents)) | |
| print(" Generation Config:", generation_config) | |
| print(" Stream:", stream) | |
| if stream: | |
| def stream_generator(): | |
| response = model.generate_content( | |
| contents, | |
| generation_config=generation_config, | |
| safety_settings=safety_settings, | |
| stream=True, | |
| ) | |
| for chunk in response: | |
| if chunk.text: | |
| yield chunk.text | |
| return stream_generator() | |
| else: | |
| response = model.generate_content( | |
| contents, | |
| generation_config=generation_config, | |
| safety_settings=safety_settings, | |
| stream=False, | |
| ) | |
| return response.text | |
| except Exception as e: | |
| if DEBUG: | |
| print(f"Error in pipe method: {e}") | |
| return f"Error: {e}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment