feat: 增强编码能力 - 新增代码编辑器、代码搜索、Git集成
- 新增 plugins/code_editor.py: 精准代码编辑(搜索替换、批量编辑、diff对比) - 新增 plugins/code_search.py: 代码搜索与理解(跨文件搜索、符号提取、依赖分析) - 新增 plugins/git_tools.py: Git 版本控制(status/diff/log/commit/branch) - 新增 core/ 模块: 配置管理、引擎管理、对话处理、显示输出、代码沙箱 - 修复 requirements.txt: 使用正确的 pip 包名(Pillow、opencv-python 等) - 更新 unified_tool_manager.py: 兼容 Plugin 和 Liugin 两种类名 - 更新系统提示词: 增强编程工作流指导 本次更新由 mimo 自动化执行,与开发者无关。
This commit is contained in:
commit
e22652fbbb
53 files changed
+20067
No files matched your search
@@ -0,0 +1,198 @@
|
||||
"""
|
||||
Ollama图像识别插件
|
||||
支持多种图像识别引擎的切换
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from colorama import Fore, Style
|
||||
|
||||
# 添加项目根目录到sys.path
|
||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
project_root = os.path.dirname(current_dir)
|
||||
sys.path.insert(0, project_root)
|
||||
|
||||
from image_engine import get_engine_manager
|
||||
|
||||
|
||||
class Liugin:
|
||||
"""图像识别插件 - 支持多引擎切换"""
|
||||
|
||||
def __init__(self):
|
||||
self.usage = """图像识别插件使用方法:
|
||||
/image <操作> <参数>
|
||||
|
||||
操作命令:
|
||||
- analyze <图片路径> - 详细分析图片
|
||||
- ocr <图片路径> - 快速OCR文字识别
|
||||
- quick <图片路径> - 快速图片描述
|
||||
- describe <图片路径> - 完整描述图片
|
||||
- model [模型名] - 查看/切换模型
|
||||
- models - 列出可用的视觉模型
|
||||
- engine [引擎名] - 查看/切换识别引擎
|
||||
- engines - 列出所有识别引擎
|
||||
|
||||
示例:
|
||||
- image analyze C:\\photo.png
|
||||
- image ocr C:\\screenshot.png
|
||||
- image model llava:13b
|
||||
- image engine openai
|
||||
|
||||
JSON调用示例:
|
||||
{"action": "use_tool", "tool": "image", "args": "analyze c:\\\\test.png"}
|
||||
"""
|
||||
self.cli = None
|
||||
self.engine_manager = None
|
||||
|
||||
# 支持的图片格式
|
||||
self.supported_formats = ['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp']
|
||||
|
||||
def set_cli(self, cli):
|
||||
"""设置CLI实例引用"""
|
||||
self.cli = cli
|
||||
# 注册插件命令
|
||||
self.cli.register_liugin_command('image', self.command_handler)
|
||||
self.cli.register_liugin_command('img', self.command_handler)
|
||||
|
||||
def command_handler(self, args):
|
||||
"""处理命令"""
|
||||
parts = args.strip().split(maxsplit=1)
|
||||
if len(parts) < 1:
|
||||
return self._get_help()
|
||||
|
||||
operation = parts[0].lower()
|
||||
remaining_args = parts[1] if len(parts) > 1 else ""
|
||||
return self.handle(f"{operation} {remaining_args}")
|
||||
|
||||
def get_tool_info(self):
|
||||
return {
|
||||
"name": "image",
|
||||
"description": "图像识别工具,支持多引擎切换,使用本地或云端模型进行图像分析",
|
||||
"keywords": ["图像", "图片", "image", "analyze", "分析", "视觉", "识别", "OCR"],
|
||||
"usage": """image 工具使用说明:
|
||||
- analyze <图片路径> - 详细分析
|
||||
- ocr <图片路径> - OCR文字识别
|
||||
- quick <图片路径> - 快速描述
|
||||
- engine <引擎名> - 切换引擎
|
||||
- engines - 列出所有引擎
|
||||
支持格式:PNG, JPG, JPEG, GIF, WEBP, BMP"""
|
||||
}
|
||||
|
||||
def handle(self, args):
|
||||
"""处理请求"""
|
||||
# 延迟初始化引擎管理器
|
||||
if self.engine_manager is None:
|
||||
self.engine_manager = get_engine_manager()
|
||||
|
||||
try:
|
||||
parts = args.strip().split(maxsplit=1)
|
||||
if len(parts) < 1:
|
||||
return self._get_help()
|
||||
|
||||
operation = parts[0].lower()
|
||||
image_path = parts[1].strip() if len(parts) > 1 else ""
|
||||
|
||||
# 引擎管理命令
|
||||
if operation == "engines":
|
||||
return self.engine_manager.list_engines()
|
||||
|
||||
elif operation == "engine":
|
||||
if image_path:
|
||||
success, msg = self.engine_manager.switch_engine(image_path)
|
||||
return msg
|
||||
return f"当前引擎: {self.engine_manager.get_current_engine_name()}"
|
||||
|
||||
elif operation == "models":
|
||||
engine = self.engine_manager.get_engine()
|
||||
if engine and hasattr(engine, 'get_model_list'):
|
||||
return engine.get_model_list()
|
||||
return "当前引擎不支持模型列表"
|
||||
|
||||
elif operation == "model":
|
||||
engine = self.engine_manager.get_engine()
|
||||
if not image_path:
|
||||
if engine and hasattr(engine, 'model'):
|
||||
return f"当前模型: {engine.model}"
|
||||
return "当前引擎不支持模型切换"
|
||||
if engine and hasattr(engine, 'set_model'):
|
||||
success, msg = engine.set_model(image_path)
|
||||
return msg
|
||||
return "当前引擎不支持模型切换"
|
||||
|
||||
# 图像分析命令
|
||||
elif operation in ["analyze", "ocr", "quick", "describe"]:
|
||||
if not image_path:
|
||||
return f"错误:请提供图片路径。用法: {operation} <图片路径>"
|
||||
return self._analyze_image(image_path, operation)
|
||||
|
||||
else:
|
||||
# 兼容旧用法,直接当作图片路径处理
|
||||
return self._analyze_image(operation, "analyze")
|
||||
|
||||
except Exception as e:
|
||||
return f"错误: {str(e)}"
|
||||
|
||||
def _get_help(self):
|
||||
"""获取帮助信息"""
|
||||
current = self.engine_manager.get_current_engine_name() if self.engine_manager else "未初始化"
|
||||
return f"""图像识别插件命令:
|
||||
- analyze <图片路径> 详细分析图片
|
||||
- ocr <图片路径> OCR文字识别
|
||||
- quick <图片路径> 快速描述
|
||||
- describe <图片路径> 完整描述
|
||||
- model [模型名] 查看/切换模型
|
||||
- models 列出视觉模型
|
||||
- engine [引擎名] 查看/切换引擎
|
||||
- engines 列出所有引擎
|
||||
|
||||
当前引擎: {current}"""
|
||||
|
||||
def _analyze_image(self, image_path, mode="analyze"):
|
||||
"""使用引擎分析图片"""
|
||||
# 检查文件
|
||||
if not os.path.exists(image_path):
|
||||
return f"文件不存在: {image_path}"
|
||||
|
||||
ext = os.path.splitext(image_path)[1].lower().lstrip('.')
|
||||
if ext not in self.supported_formats:
|
||||
return f"不支持的图片格式: {ext}。支持: {', '.join(self.supported_formats)}"
|
||||
|
||||
# 检查引擎
|
||||
engine = self.engine_manager.get_engine()
|
||||
if not engine:
|
||||
return "没有可用的图像引擎"
|
||||
|
||||
file_size = os.path.getsize(image_path)
|
||||
engine_name = self.engine_manager.get_current_engine_name()
|
||||
|
||||
# 获取模型名(如果支持)
|
||||
model_info = ""
|
||||
if hasattr(engine, 'model'):
|
||||
model_info = f" | 模型: {engine.model}"
|
||||
|
||||
# 文件大小警告
|
||||
size_warning = ""
|
||||
if file_size > 1024 * 1024: # 大于1MB
|
||||
size_warning = f" {Fore.YELLOW}(较大图片,处理可能需要较长时间){Style.RESET_ALL}"
|
||||
|
||||
print(f"{Fore.CYAN}📷 图像识别: {os.path.basename(image_path)}{Style.RESET_ALL}{size_warning}")
|
||||
print(f"{Fore.YELLOW}📦 大小: {file_size/1024:.1f}KB | 引擎: {engine_name}{model_info}{Style.RESET_ALL}")
|
||||
print(f"{Fore.YELLOW}⏳ 正在识别,请耐心等待...{Style.RESET_ALL}")
|
||||
|
||||
try:
|
||||
# 使用引擎分析
|
||||
full_response = ""
|
||||
for chunk in self.engine_manager.analyze(image_path, mode, stream=True):
|
||||
if chunk:
|
||||
print(chunk, end='', flush=True)
|
||||
full_response += chunk
|
||||
|
||||
print() # 换行
|
||||
print(f"{Fore.GREEN}✓ 识别完成{Style.RESET_ALL}")
|
||||
|
||||
return full_response if full_response else "识别结果为空"
|
||||
|
||||
except Exception as e:
|
||||
error_msg = str(e)
|
||||
print(f"{Fore.RED}✗ {error_msg}{Style.RESET_ALL}")
|
||||
return f"识别失败: {error_msg}"
|
||||
Reference in new issue
Block a user