Skip to main content
Glama

Image Analyzer MCP Server

by lucoo01
ollama_client.py9.04 kB
""" Ollama客户端模块 用于与本地Ollama服务交互,调用gemma3:12b模型进行图片分析 """ import os import base64 import requests import logging import traceback from typing import Optional, Dict, Any from PIL import Image import io from dotenv import load_dotenv # 加载环境变量 load_dotenv() # 获取日志记录器 logger = logging.getLogger(__name__) class OllamaClient: """Ollama客户端类""" def __init__(self, base_url: Optional[str] = None, model: Optional[str] = None): """ 初始化Ollama客户端 Args: base_url: Ollama服务基础URL model: 使用的模型名称 """ self.base_url = base_url or os.getenv("OLLAMA_BASE_URL", "http://localhost:11434") self.model = model or os.getenv("OLLAMA_MODEL", "gemma3:12b") self.timeout = int(os.getenv("OLLAMA_REQUEST_TIMEOUT", "180")) self.session = requests.Session() logger.info(f"初始化Ollama客户端") logger.info(f" - 基础URL: {self.base_url}") logger.info(f" - 模型: {self.model}") logger.info(f" - 请求超时: {self.timeout}秒") def health_check(self) -> bool: """ 检查Ollama服务是否健康 Returns: bool: 服务是否可用 """ logger.debug(f"检查Ollama服务健康状态: {self.base_url}/api/tags") try: response = self.session.get(f"{self.base_url}/api/tags", timeout=5) if response.status_code == 200: logger.debug("Ollama服务健康检查通过") return True else: logger.warning(f"Ollama服务健康检查失败,状态码: {response.status_code}") return False except requests.RequestException as e: logger.error(f"Ollama服务健康检查异常: {e}") logger.debug(f"异常详情: {traceback.format_exc()}") return False def list_models(self) -> Dict[str, Any]: """ 获取可用模型列表 Returns: Dict: 模型列表信息 """ try: response = self.session.get(f"{self.base_url}/api/tags", timeout=10) response.raise_for_status() return response.json() except requests.RequestException as e: raise Exception(f"获取模型列表失败: {e}") def encode_image(self, image_path: str) -> str: """ 将图片编码为base64字符串 Args: image_path: 图片文件路径 Returns: str: base64编码的图片数据 """ try: with Image.open(image_path) as img: # 转换为RGB格式(如果需要) if img.mode != 'RGB': img = img.convert('RGB') # 调整图片大小以减少token消耗 max_size = 1024 if max(img.size) > max_size: img.thumbnail((max_size, max_size), Image.Resampling.LANCZOS) # 保存到字节流 buffered = io.BytesIO() img.save(buffered, format="JPEG", quality=85) img_str = base64.b64encode(buffered.getvalue()).decode() return img_str except Exception as e: raise Exception(f"图片编码失败: {e}") def analyze_image(self, image_path: str, prompt: str = "请详细描述这张图片的内容") -> Dict[str, Any]: """ 使用gemma3:12b模型分析图片 Args: image_path: 图片文件路径 prompt: 分析提示词 Returns: Dict: 分析结果 """ logger.info(f"开始分析图片: {image_path}") logger.debug(f"使用模型: {self.model}") logger.debug(f"提示词长度: {len(prompt)} 字符") try: # 检查服务健康状态 logger.debug("检查Ollama服务健康状态...") if not self.health_check(): logger.error("Ollama服务不可用,请确保服务正在运行") raise Exception("Ollama服务不可用,请确保服务正在运行") logger.info("Ollama服务健康检查通过") # 编码图片 logger.debug("开始编码图片...") image_data = self.encode_image(image_path) logger.debug(f"图片编码完成,base64数据长度: {len(image_data)}") # 构建请求 payload = { "model": self.model, "prompt": prompt, "images": [image_data], "stream": False } logger.debug(f"构建请求负载,模型: {self.model}") logger.debug(f"请求URL: {self.base_url}/api/generate") # 发送请求 logger.info("发送图片分析请求到Ollama服务...") response = self.session.post( f"{self.base_url}/api/generate", json=payload, timeout=self.timeout # 使用环境变量配置的超时时间 ) logger.debug(f"收到响应,状态码: {response.status_code}") response.raise_for_status() result = response.json() logger.info("图片分析请求成功完成") logger.debug(f"响应数据键: {list(result.keys())}") logger.debug(f"分析完成状态: {result.get('done', False)}") logger.debug(f"总耗时: {result.get('total_duration', 0)}ms") logger.debug(f"提示词评估数量: {result.get('prompt_eval_count', 0)}") logger.debug(f"生成数量: {result.get('eval_count', 0)}") return { "success": True, "model": self.model, "response": result.get("response", ""), "done": result.get("done", False), "total_duration": result.get("total_duration", 0), "prompt_eval_count": result.get("prompt_eval_count", 0), "eval_count": result.get("eval_count", 0) } except requests.RequestException as e: logger.error(f"请求Ollama服务失败: {e}") logger.debug(f"请求异常详情: {traceback.format_exc()}") return { "success": False, "error": f"请求Ollama服务失败: {e}" } except Exception as e: logger.error(f"图片分析过程中发生异常: {e}") logger.error(f"异常堆栈: {traceback.format_exc()}") return { "success": False, "error": str(e) } def analyze_image_with_categories(self, image_path: str, categories: list = None) -> Dict[str, Any]: """ 按指定类别分析图片 Args: image_path: 图片文件路径 categories: 分析类别列表 Returns: Dict: 分类分析结果 """ if categories is None: categories = ["物体识别", "场景描述", "颜色分析", "文字内容", "情感氛围"] prompt = f"""请从以下几个方面分析这张图片: {chr(10).join([f"{i+1}. {cat}" for i, cat in enumerate(categories)])} 请为每个方面提供详细的分析结果。""" return self.analyze_image(image_path, prompt) def extract_text_from_image(self, image_path: str) -> Dict[str, Any]: """ 从图片中提取文字内容 Args: image_path: 图片文件路径 Returns: Dict: 文字提取结果 """ prompt = """请仔细观察这张图片,提取其中的所有文字内容。 包括: 1. 图片中可见的文字 2. 标题、标签、说明文字 3. 如果有表格或列表,请完整提取 4. 注意文字的语言和格式 如果没有发现文字,请明确说明。""" return self.analyze_image(image_path, prompt) # 便捷函数 def create_client() -> OllamaClient: """创建Ollama客户端实例""" return OllamaClient() if __name__ == "__main__": # 测试代码 client = OllamaClient() # 检查服务状态 if client.health_check(): print("✅ Ollama服务运行正常") # 列出可用模型 models = client.list_models() print(f"📋 可用模型: {models}") # 如果有测试图片,可以测试分析功能 # result = client.analyze_image("test.jpg") # print(f"🔍 分析结果: {result}") else: print("❌ Ollama服务不可用,请检查服务是否启动")

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/lucoo01/image-analyzer-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server