在openEuler上搞个云原生AI模型商店:像点外卖一样部署模型

文章目录

  • 一、开头
  • [二、先整个基础框架 - 模型商店的门面](#二、先整个基础框架 - 模型商店的门面)
    • [2.1 模型注册中心 - 就像餐厅的菜单](#2.1 模型注册中心 - 就像餐厅的菜单)
    • [2.2 一键部署器 - 后厨自动化系统](#2.2 一键部署器 - 后厨自动化系统)
  • [三、整个Web界面 - 让点菜变得更简单](#三、整个Web界面 - 让点菜变得更简单)
  • 四、整个简单的前端界面
  • 五、实际运行效果
  • [六、进阶功能 - 让商店更智能](#六、进阶功能 - 让商店更智能)
  • 七、总结

一、开头

兄弟们,不知道你们有没有这样的经历:想试个新AI模型,结果光环境配置就搞了半天。Python版本不对、依赖冲突、CUDA版本不匹配...每次部署都像在拆炸弹,不知道哪步会炸。

直到我在openEuler上发现了云原生的正确打开方式------现在部署AI模型就跟点外卖一样简单:选模型、点部署、等上菜。今天我就带你整一个AI模型商店,让你体验一下什么叫"科技改变生活"。

二、先整个基础框架 - 模型商店的门面

2.1 模型注册中心 - 就像餐厅的菜单

python 复制代码
# model_registry.py
from typing import Dict, List, Optional
from dataclasses import dataclass
import yaml
import json

@dataclass
class ModelInfo:
    """模型信息,就像菜单上的菜品描述"""
    name: str           # 模型名
    version: str        # 版本号  
    description: str    # 描述
    image: str         # 容器镜像地址
    framework: str     # 框架类型
    inputs: List[str]  # 输入格式
    outputs: List[str] # 输出格式
    
    def to_dict(self):
        return {
            'name': self.name,
            'version': self.version,
            'description': self.description,
            'image': self.image,
            'framework': self.frame work,
            'inputs': self.inputs,
            'outputs': self.outputs
        }

class ModelRegistry:
    """模型注册中心 - 管理所有可用的模型"""
    
    def __init__(self):
        self.models: Dict[str, ModelInfo] = {}
        self._load_default_models()
    
    def _load_default_models(self):
        """预加载一些常用模型,就像餐厅的招牌菜"""
        default_models = [
            ModelInfo(
                name="sentiment-analysis",
                version="1.0",
                description="情感分析模型,能判断文本情感倾向",
                image="registry.example.com/sentiment:v1.0",
                framework="pytorch",
                inputs=["text"],
                outputs=["sentiment", "confidence"]
            ),
            ModelInfo(
                name="image-classification", 
                version="2.1",
                description="图像分类模型,支持1000个类别",
                image="registry.example.com/classification:v2.1",
                framework="tensorflow",
                inputs=["image"],
                outputs=["class", "confidence"]
            ),
            ModelInfo(
                name="text-generation",
                version="1.5", 
                description="文本生成模型,能写文章、对话",
                image="registry.example.com/gpt:v1.5",
                framework="pytorch",
                inputs=["prompt"],
                outputs=["generated_text"]
            )
        ]
        
        for model in default_models:
            key = f"{model.name}-{model.version}"
            self.models[key] = model
    
    def list_models(self) -> List[dict]:
        """列出所有可用模型"""
        return [model.to_dict() for model in self.models.values()]
    
    def get_model(self, name: str, version: str) -> Optional[ModelInfo]:
        """根据名称和版本获取模型信息"""
        key = f"{name}-{version}"
        return self.models.get(key)
    
    def register_model(self, model_info: ModelInfo):
        """注册新模型"""
        key = f"{model_info.name}-{model_info.version}"
        self.models[key] = model_info
        print(f"✅ 模型注册成功: {model_info.name} v{model_info.version}")

# 初始化模型商店
model_store = ModelRegistry()

这个模型注册中心就像餐厅的菜单,记录了所有可用的AI模型。每个模型都有详细的描述,让用户知道这个模型能做什么、需要什么输入、会输出什么。

2.2 一键部署器 - 后厨自动化系统

python 复制代码
# deployer.py
import subprocess
import tempfile
import os
from typing import Dict, Any

class ModelDeployer:
    """模型部署器 - 负责把模型部署到Kubernetes"""
    
    def __init__(self, namespace: str = "ai-models"):
        self.namespace = namespace
        self._ensure_namespace()
    
    def _ensure_namespace(self):
        """确保命名空间存在"""
        try:
            subprocess.run([
                "kubectl", "create", "namespace", self.namespace
            ], capture_output=True, check=False)
            print(f"📁 使用命名空间: {self.namespace}")
        except Exception as e:
            print(f"⚠️  命名空间检查失败: {e}")
    
    def generate_deployment_yaml(self, model_info, deployment_name: str) -> str:
        """生成Kubernetes部署文件"""
        
        deployment = {
            "apiVersion": "apps/v1",
            "kind": "Deployment",
            "metadata": {
                "name": deployment_name,
                "namespace": self.namespace,
                "labels": {
                    "app": model_info.name,
                    "version": model_info.version
                }
            },
            "spec": {
                "replicas": 1,
                "selector": {
                    "matchLabels": {
                        "app": model_info.name
                    }
                },
                "template": {
                    "metadata": {
                        "labels": {
                            "app": model_info.name
                        }
                    },
                    "spec": {
                        "containers": [{
                            "name": model_info.name,
                            "image": model_info.image,
                            "ports": [{
                                "containerPort": 8080
                            }],
                            "env": [
                                {
                                    "name": "MODEL_NAME",
                                    "value": model_info.name
                                },
                                {
                                    "name": "MODEL_VERSION", 
                                    "value": model_info.version
                                }
                            ],
                            "resources": {
                                "requests": {
                                    "memory": "512Mi",
                                    "cpu": "250m"
                                },
                                "limits": {
                                    "memory": "1Gi", 
                                    "cpu": "500m"
                                }
                            },
                            "livenessProbe": {
                                "httpGet": {
                                    "path": "/health",
                                    "port": 8080
                                },
                                "initialDelaySeconds": 30,
                                "periodSeconds": 10
                            },
                            "readinessProbe": {
                                "httpGet": {
                                    "path": "/health",
                                    "port": 8080
                                },
                                "initialDelaySeconds": 5,
                                "periodSeconds": 5
                            }
                        }]
                    }
                }
            }
        }
        
        service = {
            "apiVersion": "v1",
            "kind": "Service",
            "metadata": {
                "name": f"{deployment_name}-service",
                "namespace": self.namespace
            },
            "spec": {
                "selector": {
                    "app": model_info.name
                },
                "ports": [{
                    "port": 80,
                    "targetPort": 8080
                }],
                "type": "ClusterIP"
            }
        }
        
        return yaml.dump_all([deployment, service], default_flow_style=False)
    
    def deploy_model(self, model_info, deployment_name: str) -> bool:
        """部署模型到Kubernetes"""
        try:
            print(f"🚀 开始部署模型: {model_info.name} v{model_info.version}")
            
            # 生成部署文件
            yaml_content = self.generate_deployment_yaml(model_info, deployment_name)
            
            # 创建临时文件并应用
            with tempfile.NamedTemporaryFile(mode='w', suffix='.yaml', delete=False) as f:
                f.write(yaml_content)
                temp_file = f.name
            
            # 执行部署命令
            result = subprocess.run([
                "kubectl", "apply", "-f", temp_file
            ], capture_output=True, text=True, check=True)
            
            # 清理临时文件
            os.unlink(temp_file)
            
            print(f"✅ 模型部署成功: {deployment_name}")
            print(f"📊 部署状态: {result.stdout}")
            return True
            
        except subprocess.CalledProcessError as e:
            print(f"❌ 部署失败: {e.stderr}")
            return False
        except Exception as e:
            print(f"💥 部署过程出错: {e}")
            return False
    
    def check_deployment_status(self, deployment_name: str) -> Dict[str, Any]:
        """检查部署状态"""
        try:
            # 检查Deployment状态
            result = subprocess.run([
                "kubectl", "get", "deployment", deployment_name,
                "-n", self.namespace, "-o", "json"
            ], capture_output=True, text=True, check=True)
            
            status = json.loads(result.stdout)
            
            # 检查Pod状态
            pods_result = subprocess.run([
                "kubectl", "get", "pods", 
                "-n", self.namespace,
                "-l", f"app={deployment_name}",
                "-o", "json"
            ], capture_output=True, text=True, check=True)
            
            pods_status = json.loads(pods_result.stdout)
            
            return {
                "deployment": status,
                "pods": pods_status
            }
            
        except Exception as e:
            return {"error": str(e)}

# 初始化部署器
deployer = ModelDeployer()

这个部署器就是我们的"自动化后厨",你点个菜(模型),它就能自动准备食材(容器镜像)、开火烹饪(部署服务)、摆盘上菜(暴露服务)。

三、整个Web界面 - 让点菜变得更简单

python 复制代码
# app.py
from flask import Flask, render_template, request, jsonify, session
import uuid
import time

app = Flask(__name__)
app.secret_key = 'your-secret-key-here'

@app.route('/')
def index():
    """模型商店首页"""
    models = model_store.list_models()
    return render_template('index.html', models=models)

@app.route('/api/models')
def list_models_api():
    """获取模型列表API"""
    models = model_store.list_models()
    return jsonify({"models": models})

@app.route('/model/<name>/<version>')
def model_detail(name, version):
    """模型详情页面"""
    model = model_store.get_model(name, version)
    if not model:
        return "Model not found", 404
    
    return render_template('model_detail.html', model=model.to_dict())

@app.route('/api/deploy', methods=['POST'])
def deploy_model():
    """部署模型API"""
    data = request.json
    model_name = data.get('name')
    model_version = data.get('version')
    deployment_name = data.get('deployment_name', f"{model_name}-{str(uuid.uuid4())[:8]}")
    
    # 获取模型信息
    model = model_store.get_model(model_name, model_version)
    if not model:
        return jsonify({"error": "Model not found"}), 404
    
    # 执行部署
    success = deployer.deploy_model(model, deployment_name)
    
    if success:
        return jsonify({
            "success": True,
            "deployment_name": deployment_name,
            "message": "模型部署成功"
        })
    else:
        return jsonify({
            "success": False, 
            "message": "模型部署失败"
        }), 500

@app.route('/api/status/<deployment_name>')
def get_deployment_status(deployment_name):
    """获取部署状态"""
    status = deployer.check_deployment_status(deployment_name)
    return jsonify(status)

@app.route('/api/test/<model_name>')
def test_model(model_name):
    """测试模型API(简化版)"""
    # 这里应该是实际的模型调用逻辑
    # 为了演示,我们返回模拟结果
    
    test_results = {
        "sentiment-analysis": {
            "input": "这个产品真的很棒,我非常喜欢!",
            "output": {
                "sentiment": "positive",
                "confidence": 0.95
            }
        },
        "image-classification": {
            "input": "cat_image.jpg", 
            "output": {
                "class": "cat",
                "confidence": 0.89
            }
        },
        "text-generation": {
            "input": "请写一段关于AI的短文",
            "output": {
                "generated_text": "人工智能正在改变世界..."
            }
        }
    }
    
    result = test_results.get(model_name, {"error": "Test not available"})
    return jsonify(result)

if __name__ == '__main__':
    print("🎉 AI模型商店启动成功!")
    print("📍 访问地址: http://localhost:5000")
    print("📚 可用模型:", len(model_store.list_models()))
    app.run(host='0.0.0.0', port=5000, debug=True)

四、整个简单的前端界面

python 复制代码
<!-- templates/index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>AI模型商店 - 像点外卖一样部署模型</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .model-card { 
            border: 1px solid #ddd; 
            padding: 20px; 
            margin: 10px; 
            border-radius: 8px;
            display: inline-block;
            width: 300px;
            vertical-align: top;
        }
        .model-card h3 { color: #333; margin-top: 0; }
        .btn { 
            background: #007bff; 
            color: white; 
            padding: 10px 15px;
            border: none; 
            border-radius: 4px; 
            cursor: pointer;
            text-decoration: none;
            display: inline-block;
        }
        .btn:hover { background: #0056b3; }
        .status { padding: 5px 10px; border-radius: 3px; }
        .status-deploying { background: #fff3cd; color: #856404; }
        .status-running { background: #d1ecf1; color: #0c5460; }
    </style>
</head>
<body>
    <h1>🤖 AI模型商店</h1>
    <p>选择你需要的AI模型,一键部署到openEuler云原生环境</p>
    
    <div id="models-container">
        {% for model in models %}
        <div class="model-card">
            <h3>{{ model.name }} v{{ model.version }}</h3>
            <p>{{ model.description }}</p>
            <p><strong>框架:</strong> {{ model.framework }}</p>
            <p><strong>输入:</strong> {{ model.inputs | join(', ') }}</p>
            <p><strong>输出:</strong> {{ model.outputs | join(', ') }}</p>
            
            <div style="margin-top: 15px;">
                <button class="btn" onclick="deployModel('{{ model.name }}', '{{ model.version }}')">
                    🚀 一键部署
                </button>
                <a href="/model/{{ model.name }}/{{ model.version }}" class="btn" style="background: #6c757d;">
                    📖 查看详情
                </a>
            </div>
            
            <div id="status-{{ model.name }}-{{ model.version }}" style="margin-top: 10px;"></div>
        </div>
        {% endfor %}
    </div>

    <script>
        async function deployModel(name, version) {
            const statusDiv = document.getElementById(`status-${name}-${version}`);
            statusDiv.innerHTML = '<div class="status status-deploying">部署中...</div>';
            
            try {
                const response = await fetch('/api/deploy', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                        name: name,
                        version: version
                    })
                });
                
                const result = await response.json();
                
                if (result.success) {
                    statusDiv.innerHTML = '<div class="status status-running">✅ 部署成功!</div>';
                    // 可以在这里添加更多交互,比如查看服务状态、测试模型等
                    setTimeout(() => {
                        testModel(name);
                    }, 2000);
                } else {
                    statusDiv.innerHTML = '<div style="color: red;">❌ 部署失败: ' + result.message + '</div>';
                }
            } catch (error) {
                statusDiv.innerHTML = '<div style="color: red;">💥 请求失败: ' + error + '</div>';
            }
        }
        
        async function testModel(name) {
            try {
                const response = await fetch(`/api/test/${name}`);
                const result = await response.json();
                console.log('测试结果:', result);
                alert(`模型测试完成!\n输入: ${result.input}\n输出: ${JSON.stringify(result.output)}`);
            } catch (error) {
                console.error('测试失败:', error);
            }
        }
    </script>
</body>
</html>

五、实际运行效果

当你运行这个系统时,会看到这样的输出:

打开浏览器访问 http://localhost:5000,你会看到一个漂亮的模型商店界面,里面有各种AI模型卡片。

六、进阶功能 - 让商店更智能

python 复制代码
# 添加模型监控和自动扩缩
class SmartModelManager:
    """智能模型管理器"""
    
    def __init__(self):
        self.deployments = {}
    
    def setup_auto_scaling(self, deployment_name: str):
        """设置自动扩缩容"""
        hpa_yaml = f"""
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: {deployment_name}-hpa
  namespace: ai-models
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: {deployment_name}
  minReplicas: 1
  maxReplicas: 5
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
"""
        # 应用HPA配置
        with tempfile.NamedTemporaryFile(mode='w', suffix='.yaml') as f:
            f.write(hpa_yaml)
            f.flush()
            subprocess.run(["kubectl", "apply", "-f", f.name], check=True)
        
        print(f"📈 已为 {deployment_name} 设置自动扩缩容")
    
    def setup_monitoring(self, deployment_name: str):
        """设置监控"""
        # 添加Prometheus监控注解
        subprocess.run([
            "kubectl", "annotate", "deployment", deployment_name,
            "-n", "ai-models",
            "prometheus.io/scrape=true",
            "prometheus.io/port=8080"
        ], check=True)
        
        print(f"📊 已为 {deployment_name} 设置监控")

# 使用智能管理器
smart_manager = SmartModelManager()

七、总结

通过这个AI模型商店,你会发现:

传统部署 vs 云原生部署

  • ❌ 传统:配环境、装依赖、调参数、手动部署
  • ✅ 云原生:点按钮、等部署、直接用

在openEuler上的优势

  • 🚀 性能优化:容器运行时经过深度优化
  • 🔒 安全可靠:内置安全增强特性
  • 📦 生态完善:丰富的云原生工具链
  • 🎯 简单易用:K3s让Kubernetes变得亲民

现在部署AI模型真的就像点外卖一样简单:

  1. 浏览菜单(查看可用模型)
  2. 选择菜品(点击部署按钮)
  3. 等待配送(自动部署过程)
  4. 享受美食(使用模型服务)

最重要的是,这一切都是在openEuler这个自主创新的平台上实现的,既保证了技术先进性,又确保了系统安全可控。

所以,别再手动折腾环境配置了,试试这个云原生AI模型商店,你会发现部署AI模型原来可以这么轻松愉快!

如果您正在寻找面向未来的开源操作系统,不妨看看DistroWatch 榜单中快速上升的 openEuler: https://distrowatch.com/table-mobile.php?distribution=openeuler,一个由开放原子开源基金会孵化、支持"超节点"场景的Linux 发行版。

openEuler官网:https://www.openeuler.openatom.cn/zh/

相关推荐
lomocode1 小时前
Dify 自建部署完全指南:从上手到放弃到真香
人工智能
aaaa_a1332 小时前
李宏毅——self-attention Transformer
人工智能·深度学习·transformer
Coovally AI模型快速验证2 小时前
MAR-YOLOv9:革新农业检测,YOLOv9的“低调”逆袭
人工智能·神经网络·yolo·计算机视觉·cnn
云和数据.ChenGuang2 小时前
AI运维工程师技术教程之Linux环境下部署Deepseek
linux·运维·人工智能
cvyoutian2 小时前
解决 PyTorch 大型 wheel 下载慢、超时和反复重下的问题
人工智能·pytorch·python
oliveray2 小时前
解决开放世界目标检测问题——Grounding DINO
人工智能·目标检测·计算机视觉
阿里云云原生2 小时前
线下活动速递丨AI 原生应用开源开发者沙龙·杭州站
云原生
子非鱼9212 小时前
3 传统序列模型——RNN
人工智能·rnn·深度学习
万俟淋曦3 小时前
【论文速递】2025年第33周(Aug-10-16)(Robotics/Embodied AI/LLM)
人工智能·深度学习·ai·机器人·论文·robotics·具身智能