1. Claude Code API调用与Agent Skills核心概念
在开始探讨API调用最佳实践之前,我们需要先明确几个核心概念。Claude Code作为新一代AI开发平台,其Agent Skills机制是其最具创新性的功能之一。
1.1 Agent Skills的本质
Agent Skills不是简单的代码片段集合,而是一种模块化的能力封装。每个Skill都包含:
- 核心功能实现(Python/JavaScript代码)
- 配置文件(skill.yaml)
- 文档说明(README.md)
- 测试用例(tests/)
- 资源文件(assets/)
这种结构设计使得Skills可以像乐高积木一样被组合使用。例如,一个"天气查询"Skill可能包含:
# weather_skill/main.py def get_weather(location: str, api_key: str) -> dict: """获取指定地点的天气数据""" # 实际API调用逻辑...1.2 API调用的基础架构
Claude Code的API调用采用分层设计:
- 传输层:基于HTTP/2的gRPC协议
- 认证层:JWT令牌验证
- 路由层:智能负载均衡
- 执行层:隔离的沙箱环境
这种架构保证了API调用的高效性和安全性。一个典型的调用流程如下:
sequenceDiagram Client->>+API Gateway: 认证请求 API Gateway->>+Skill Router: 路由请求 Skill Router->>+Skill Executor: 分发任务 Skill Executor->>+Result Aggregator: 返回结果 Result Aggregator->>+Client: 最终响应2. API调用最佳实践详解
2.1 认证与安全
安全是API调用的首要考虑因素。我们推荐以下实践:
2.1.1 密钥管理
- 使用环境变量存储API密钥
- 实现密钥自动轮换机制
- 为不同环境(dev/staging/prod)使用独立密钥
示例代码:
import os from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv('CLAUDE_API_KEY') if not API_KEY: raise ValueError("Missing API key in environment variables")2.1.2 请求签名
对重要请求添加数字签名:
import hashlib import hmac import time def sign_request(secret: str, payload: dict) -> str: timestamp = str(int(time.time())) message = timestamp + json.dumps(payload) signature = hmac.new( secret.encode(), message.encode(), hashlib.sha256 ).hexdigest() return f"{timestamp}:{signature}"2.2 性能优化
2.2.1 连接池管理
建立HTTP连接池避免重复握手:
import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry session = requests.Session() retries = Retry( total=3, backoff_factor=0.1, status_forcelist=[500, 502, 503, 504] ) session.mount('https://', HTTPAdapter(max_retries=retries))2.2.2 批量请求处理
对于多个关联请求,使用批量API:
async def batch_requests(skill_name: str, requests: list): from claude_sdk import AsyncClient client = AsyncClient() batch = client.create_batch() for req in requests: batch.add(skill_name, req) results = await batch.execute() return [r.data for r in results]2.3 错误处理与重试
2.3.1 智能重试策略
实现指数退避重试机制:
import random import time def exponential_backoff(retries: int): base_delay = 0.1 max_delay = 5.0 for i in range(retries): delay = min(base_delay * (2 ** i) + random.uniform(0, 0.1), max_delay) time.sleep(delay) yield i2.3.2 错误分类处理
ERROR_MAPPING = { 400: "InvalidRequestError", 401: "AuthenticationError", 403: "PermissionDeniedError", 429: "RateLimitError", 500: "ServerError" } def handle_api_error(response): error_type = ERROR_MAPPING.get(response.status_code, "UnknownError") raise globals()[error_type](f"API Error {response.status_code}: {response.text}")3. Agent Skills开发规范
3.1 Skill结构设计
标准Skill目录结构:
my_skill/ ├── skill.yaml # 元数据配置 ├── main.py # 主逻辑 ├── requirements.txt # 依赖 ├── tests/ # 测试用例 │ ├── unit/ │ └── integration/ ├── docs/ # 文档 │ ├── README.md │ └── examples.md └── assets/ # 静态资源skill.yaml示例:
name: weather_skill version: 1.0.0 description: 提供全球天气查询功能 entry_point: main:get_weather parameters: location: type: string required: true description: 城市名称或坐标 unit: type: string enum: [celsius, fahrenheit] default: celsius3.2 输入验证模式
使用Pydantic进行强类型校验:
from pydantic import BaseModel, validator class WeatherRequest(BaseModel): location: str unit: str = "celsius" @validator('location') def validate_location(cls, v): if len(v) < 2: raise ValueError("Location too short") return v.title()3.3 测试策略
3.3.1 单元测试示例
import pytest from main import get_weather @pytest.mark.asyncio async def test_get_weather(): # 使用mock替换实际API调用 with patch('main.weather_api') as mock_api: mock_api.return_value = {"temp": 25, "condition": "sunny"} result = await get_weather("Paris") assert result["temp"] == 25 mock_api.assert_called_once()3.3.2 集成测试策略
@pytest.mark.integration class TestWeatherSkill: @classmethod def setup_class(cls): cls.client = TestClient(app) def test_happy_path(self): response = self.client.post( "/weather", json={"location": "London"} ) assert response.status_code == 200 assert "temp" in response.json()4. 高级技巧与实战经验
4.1 上下文传递模式
在链式调用中保持上下文:
def with_context(func): def wrapper(*args, **kwargs): context = kwargs.pop('context', {}) # 注入追踪ID等上下文信息 headers = { 'X-Request-ID': context.get('request_id', ''), 'X-Session-ID': context.get('session_id', '') } return func(*args, **kwargs, headers=headers) return wrapper4.2 性能监控集成
添加Prometheus监控指标:
from prometheus_client import Counter, Histogram API_CALLS = Counter( 'skill_api_calls_total', 'Total API calls', ['skill', 'status'] ) LATENCY = Histogram( 'skill_api_latency_seconds', 'API latency distribution', ['skill'] ) def monitor_api(func): async def wrapped(*args, **kwargs): start = time.time() try: result = await func(*args, **kwargs) API_CALLS.labels(skill=func.__name__, status='success').inc() return result except Exception: API_CALLS.labels(skill=func.__name__, status='error').inc() raise finally: LATENCY.labels(skill=func.__name__).observe(time.time() - start) return wrapped4.3 缓存策略实现
多级缓存方案:
from functools import lru_cache import redis # 内存缓存 @lru_cache(maxsize=1024) def memory_cache(key): return None # Redis缓存 redis_client = redis.Redis() def get_with_cache(key, ttl=300): # 1. 检查内存缓存 result = memory_cache(key) if result: return result # 2. 检查Redis缓存 result = redis_client.get(key) if result: memory_cache[key] = result # 回填内存缓存 return result # 3. 实际API调用 result = call_api(key) # 更新缓存 memory_cache[key] = result redis_client.setex(key, ttl, result) return result5. 调试与问题排查
5.1 日志记录规范
结构化日志配置:
import logging import json_log_formatter formatter = json_log_formatter.JSONFormatter() handler = logging.StreamHandler() handler.setFormatter(formatter) logger = logging.getLogger('skill') logger.addHandler(handler) logger.setLevel(logging.INFO) def log_api_call(skill, params, duration, status): logger.info({ "event": "api_call", "skill": skill, "params": params, "duration_ms": duration*1000, "status": status, "context": get_current_context() })5.2 常见错误代码
典型错误及解决方案:
| 错误代码 | 原因 | 解决方案 |
|---|---|---|
| 400 | 无效参数 | 检查输入是否符合schema |
| 401 | 认证失败 | 验证API密钥是否有效 |
| 403 | 权限不足 | 检查Skill访问权限 |
| 429 | 速率限制 | 实现退避重试机制 |
| 500 | 服务端错误 | 检查服务状态并重试 |
5.3 调试工具链
推荐调试工具组合:
- 请求追踪:Charles/Fiddler
- 性能分析:Py-Spy/pyflame
- 内存分析:memray
- 日志分析:ELK Stack
调试示例:
# 使用Py-Spy进行性能分析 py-spy top --pid $(pgrep -f my_skill) # 使用memray检查内存泄漏 memray run -o mem.bin -- python my_skill/main.py memray flamegraph mem.bin6. 性能调优实战
6.1 并发控制模式
智能并发限制实现:
from asyncio import Semaphore import asyncio class ConcurrentLimiter: def __init__(self, max_concurrent): self.semaphore = Semaphore(max_concurrent) async def run(self, coro): async with self.semaphore: return await coro limiter = ConcurrentLimiter(10) async def batch_process(tasks): return await asyncio.gather( *[limiter.run(task) for task in tasks] )6.2 连接池优化
gRPC连接池配置:
from grpc import aio channel = aio.insecure_channel( 'claude-api:50051', options=[ ('grpc.max_send_message_length', 100 * 1024 * 1024), ('grpc.max_receive_message_length', 100 * 1024 * 1024), ('grpc.enable_retries', 1), ('grpc.keepalive_time_ms', 30000), ] )6.3 负载测试方案
使用Locust进行压力测试:
from locust import HttpUser, task, between class SkillUser(HttpUser): wait_time = between(0.5, 2) @task def call_skill(self): self.client.post( "/api/skills/weather", json={"location": "Tokyo"}, headers={"Authorization": f"Bearer {API_KEY}"} )执行测试:
locust -f locustfile.py --headless -u 100 -r 10 -t 5m7. 安全加固措施
7.1 输入净化处理
防御性编程示例:
import html import re def sanitize_input(input_str: str) -> str: # 移除HTML标签 clean = re.sub(r'<[^>]+>', '', input_str) # 转义特殊字符 clean = html.escape(clean) # 限制长度 return clean[:1000]7.2 权限最小化原则
基于角色的访问控制:
from functools import wraps def require_role(role): def decorator(f): @wraps(f) async def wrapped(*args, **kwargs): current_role = get_current_role() if current_role != role: raise PermissionError(f"Requires {role} role") return await f(*args, **kwargs) return wrapped return decorator @require_role('admin') async def delete_skill(skill_id): # 管理员专属操作7.3 敏感数据保护
加密存储实现:
from cryptography.fernet import Fernet key = Fernet.generate_key() cipher = Fernet(key) def encrypt_data(data: str) -> bytes: return cipher.encrypt(data.encode()) def decrypt_data(token: bytes) -> str: return cipher.decrypt(token).decode()8. 持续集成与部署
8.1 CI/CD流水线设计
GitHub Actions示例:
name: Skill CI on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: python-version: '3.10' - run: pip install -r requirements.txt - run: pytest --cov=./ --cov-report=xml - uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} deploy: needs: test if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 - run: pip install . - run: skill-cli deploy --env prod env: CLAUDE_API_KEY: ${{ secrets.PROD_API_KEY }}8.2 版本兼容性管理
语义化版本控制策略:
from packaging import version def check_version_compatibility(current, required): """检查版本兼容性""" current_v = version.parse(current) required_v = version.parse(required) if current_v.major != required_v.major: return False if current_v < required_v: return False return True8.3 回滚机制实现
自动回滚脚本:
import subprocess from datetime import datetime def rollback(skill_name, target_version): backup_dir = f"/backups/{skill_name}" versions = sorted(os.listdir(backup_dir)) if target_version == 'latest': target = versions[-1] else: target = next((v for v in versions if v == target_version), None) if not target: raise ValueError(f"Version {target_version} not found") subprocess.run([ 'skill-cli', 'deploy', '--from-backup', os.path.join(backup_dir, target) ], check=True) logger.info(f"Rolled back {skill_name} to {target}")9. 监控与告警体系
9.1 健康检查实现
综合健康检查端点:
from fastapi import APIRouter router = APIRouter() @router.get("/health") async def health_check(): checks = { 'database': check_db(), 'cache': check_cache(), 'external_api': check_api() } status = all(checks.values()) return { 'status': 'healthy' if status else 'unhealthy', 'checks': checks }9.2 指标采集方案
Prometheus指标暴露:
from prometheus_client import start_http_server def setup_monitoring(port=8000): start_http_server(port) # 注册自定义指标 REGISTRY.register(CustomCollector()) class CustomCollector: def collect(self): yield GaugeMetric( 'skill_runtime_seconds', 'Skill execution time', value=get_runtime() )9.3 智能告警规则
动态阈值告警配置:
def dynamic_alert_threshold(metric): # 基于历史数据计算动态阈值 history = get_metric_history(metric, '7d') avg = sum(history) / len(history) std = (sum((x - avg)**2 for x in history) / len(history))**0.5 return avg + 3 * std10. 技能组合与编排
10.1 工作流引擎集成
使用Airflow编排Skills:
from airflow import DAG from airflow.operators.python import PythonOperator from datetime import datetime def create_skill_dag(skill_sequence): dag = DAG( 'skill_workflow', schedule_interval=None, start_date=datetime(2023, 1, 1) ) prev_task = None for i, skill in enumerate(skill_sequence): task = PythonOperator( task_id=f'skill_{i}', python_callable=execute_skill, op_kwargs={'skill': skill}, dag=dag ) if prev_task: prev_task >> task prev_task = task return dag10.2 条件执行逻辑
基于上下文的技能路由:
def route_skill(context): if context.get('user_tier') == 'premium': return execute_premium_skill(context) elif context.get('urgency') == 'high': return execute_fast_skill(context) else: return execute_standard_skill(context)10.3 结果聚合模式
多技能结果聚合:
async def aggregate_results(skill_results): from collections import defaultdict aggregated = defaultdict(list) for result in skill_results: for key, value in result.items(): aggregated[key].append(value) # 应用聚合策略 final_result = {} for key, values in aggregated.items(): if key.endswith('_avg'): final_result[key] = sum(values) / len(values) elif key.endswith('_sum'): final_result[key] = sum(values) else: final_result[key] = values[-1] # 默认取最新 return final_result11. 技能市场与分发
11.1 私有技能仓库
搭建私有Registry:
from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware app = FastAPI() app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"], ) @app.post("/skills/publish") async def publish_skill(skill: SkillPackage): validate_skill(skill) store_skill(skill) return {"status": "published"} @app.get("/skills/{skill_name}") async def get_skill(skill_name: str): return load_skill(skill_name)11.2 技能签名验证
数字签名验证流程:
import hashlib import json from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import padding def verify_skill(skill_path, public_key): # 1. 计算技能包哈希 with open(skill_path, 'rb') as f: digest = hashlib.sha256(f.read()).digest() # 2. 验证签名 signature = load_signature(skill_path) public_key.verify( signature, digest, padding.PSS( mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH ), hashes.SHA256() )11.3 依赖解析算法
技能依赖关系解析:
def resolve_dependencies(skills): graph = {} for skill in skills: graph[skill.name] = set(skill.dependencies) # 拓扑排序 ordered = [] while graph: # 找出无依赖的节点 ready = [name for name, deps in graph.items() if not deps] if not ready: raise ValueError("Circular dependency detected") # 处理这些节点 for name in ready: ordered.append(name) del graph[name] # 从其他节点的依赖中移除 for other in graph: if name in graph[other]: graph[other].remove(name) return ordered12. 前沿技术与未来演进
12.1 自适应技能加载
运行时技能发现:
import importlib import pkgutil def discover_skills(): skills = {} for finder, name, _ in pkgutil.iter_modules(): if name.startswith('skill_'): module = importlib.import_module(name) if hasattr(module, 'register_skill'): skills[name] = module.register_skill() return skills12.2 技能性能预测
基于机器学习的预测模型:
from sklearn.ensemble import RandomForestRegressor import numpy as np class PerformancePredictor: def __init__(self): self.model = RandomForestRegressor() def train(self, X, y): self.model.fit(X, y) def predict(self, skill_metadata): features = self._extract_features(skill_metadata) return self.model.predict([features])[0] def _extract_features(self, skill): return np.array([ len(skill.code), skill.complexity, len(skill.dependencies) ])12.3 自动技能优化
代码优化建议生成:
import ast from ast import NodeVisitor class OptimizationVisitor(NodeVisitor): def __init__(self): self.suggestions = [] def visit_For(self, node): # 检查是否可以使用列表推导 if self._is_simple_loop(node): self.suggestions.append( f"Consider using list comprehension at line {node.lineno}" ) self.generic_visit(node) def _is_simple_loop(self, node): # 简化判断逻辑 return ( isinstance(node.target, ast.Name) and len(node.body) == 1 and isinstance(node.body[0], ast.Assign) ) def analyze_skill(code): tree = ast.parse(code) visitor = OptimizationVisitor() visitor.visit(tree) return visitor.suggestions13. 实战案例:天气预报技能完整实现
13.1 需求分析
天气预报技能需要满足:
- 支持城市名称/坐标查询
- 返回温度、天气状况、湿度等数据
- 支持摄氏度/华氏度切换
- 提供天气预报缓存
13.2 代码实现
完整技能代码:
import os import json import time from datetime import datetime, timedelta from typing import Optional from fastapi import FastAPI, HTTPException from pydantic import BaseModel import requests import redis app = FastAPI() redis_client = redis.Redis(host='redis', port=6379) class WeatherRequest(BaseModel): location: str unit: str = "celsius" lang: str = "en" class WeatherResponse(BaseModel): temp: float feels_like: float condition: str humidity: float wind_speed: float forecast: list def get_cache_key(request: WeatherRequest) -> str: return f"weather:{request.location}:{request.unit}:{request.lang}" @app.post("/weather", response_model=WeatherResponse) async def get_weather(request: WeatherRequest): cache_key = get_cache_key(request) # 尝试从缓存获取 cached = redis_client.get(cache_key) if cached: return json.loads(cached) # 调用外部API api_key = os.getenv("WEATHER_API_KEY") if not api_key: raise HTTPException(status_code=500, detail="API key not configured") try: response = requests.get( "https://api.weatherapi.com/v1/current.json", params={ "key": api_key, "q": request.location, "lang": request.lang }, timeout=5 ) response.raise_for_status() data = response.json() # 转换单位 if request.unit == "fahrenheit": temp = data["current"]["temp_f"] feels_like = data["current"]["feelslike_f"] else: temp = data["current"]["temp_c"] feels_like = data["current"]["feelslike_c"] result = WeatherResponse( temp=temp, feels_like=feels_like, condition=data["current"]["condition"]["text"], humidity=data["current"]["humidity"], wind_speed=data["current"]["wind_kph"], forecast=get_forecast(data["location"]) ) # 缓存结果(5分钟) redis_client.setex( cache_key, timedelta(minutes=5), json.dumps(result.dict()) ) return result except requests.RequestException as e: raise HTTPException(status_code=502, detail=str(e)) def get_forecast(location) -> list: # 简化实现,实际应调用预报API return [ {"date": "tomorrow", "condition": "Sunny", "max_temp": 25}, {"date": "day_after", "condition": "Cloudy", "max_temp": 22} ]13.3 测试用例
完整测试套件:
import pytest from fastapi.testclient import TestClient from main import app, get_cache_key from models import WeatherRequest client = TestClient(app) def test_cache_key_generation(): request = WeatherRequest( location="London", unit="celsius", lang="en" ) assert get_cache_key(request) == "weather:London:celsius:en" @pytest.mark.asyncio async def test_weather_api_success(httpx_mock): httpx_mock.add_response( url="https://api.weatherapi.com/v1/current.json?key=test&q=Paris&lang=en", json={ "current": { "temp_c": 20, "feelslike_c": 19, "condition": {"text": "Sunny"}, "humidity": 50, "wind_kph": 15 }, "location": {} } ) os.environ["WEATHER_API_KEY"] = "test" response = client.post( "/weather", json={"location": "Paris"} ) assert response.status_code == 200 assert response.json()["temp"] == 20 def test_weather_api_failure(httpx_mock): httpx_mock.add_exception( requests.ConnectTimeout("API timeout") ) response = client.post( "/weather", json={"location": "Unknown"} ) assert response.status_code == 50214. 性能基准测试报告
14.1 测试环境配置
硬件规格:
- CPU: 8核 Intel Xeon 3.0GHz
- 内存: 32GB DDR4
- 网络: 10Gbps
- 存储: NVMe SSD
软件环境:
- Python 3.10
- FastAPI 0.95+
- Redis 7.0
- 测试工具: Locust 2.15
14.2 测试结果数据
| 并发用户数 | 平均响应时间(ms) | 吞吐量(req/s) | 错误率 |
|---|---|---|---|
| 10 | 45 | 220 | 0% |
| 50 | 62 | 800 | 0% |
| 100 | 85 | 1150 | 0% |
| 200 | 130 | 1500 | 0.2% |
| 500 | 320 | 1550 | 1.5% |
14.3 优化建议
基于测试结果的改进方向:
- 缓存层扩展:增加本地内存缓存作为Redis前置
- 连接池调优:增大HTTP客户端连接池大小
- 结果压缩:对大型响应启用gzip压缩
- 异步I/O优化:使用更高效的异步HTTP客户端
15. 技能维护与迭代
15.1 版本升级策略
语义化版本升级流程:
def upgrade_skill(skill_name, target_version): current = get_current_version(skill_name) target = resolve_version(skill_name, target_version) if target.major > current.major: # 大版本升级需要确认 if not confirm_major_upgrade(): return False # 执行迁移脚本 run_migration_scripts(current, target) # 下载新版本 download_skill(skill_name, target) # 验证兼容性 if not verify_compatibility(): rollback(skill_name, current) return False # 切换版本 activate_version(skill_name, target) return True15.2 变更日志规范
变更日志示例:
# Changelog ## [2.1.0] - 2023-06-15 ### Added - 支持新的天气数据源API - 添加空气质量指数(AQI)返回字段 ### Changed - 优化缓存策略,TTL从5分钟增加到15分钟 - 更新依赖库到最新稳定版 ### Fixed - 修复坐标查询时的边界条件错误 - 解决时区处理不一致问题15.3 废弃流程管理
技能废弃声明:
def deprecate_skill(skill_name, replacement=None): set_status(skill_name, "deprecated") if replacement: add_redirection(skill_name, replacement) # 通知所有使用者 notify_users(skill_name, replacement) # 计划下线 schedule_removal(skill_name, timedelta(days=90))16. 技能文档标准
16.1 文档结构要求
标准文档目录:
docs/ ├── README.md # 快速入门 ├── API_REFERENCE.md # API详细说明 ├── EXAMPLES.md # 使用示例 ├── TROUBLESHOOTING.md # 问题排查 └── CHANGELOG.md # 变更历史16.2 示例代码规范
示例代码标准:
## 基本使用 获取当前天气: ```python from weather_skill import get_weather response = get_weather("London") print(f"Current temperature: {response.temp}°C") ``` ## 高级选项 使用华氏度并指定语言: ```python response = get_weather( location="Tokyo", unit="fahrenheit", lang="ja" ) ```16.3 多语言支持
国际化文档结构:
docs/ ├── en/ # 英文文档 │ ├── README.md │ └── ... ├── zh/ # 中文文档 │ ├── README.md │ └── ... └── ja/ # 日文文档 ├── README.md └── ...17. 技能生态系统集成
17.1 与CI/CD工具集成
Jenkins集成示例:
pipeline { agent any stages { stage('Test') { steps { sh 'python -m pytest tests/' } } stage('Deploy') { when { branch 'main' } steps { withCredentials([string( credentialsId: 'claude-api-key', variable: 'API_KEY' )]) { sh 'skill-cli deploy --env prod' } } } } }17.2 与监控系统集成
Grafana仪表板配置:
{ "panels": [ { "title": "API调用次数", "type": "stat", "targets": [{ "expr": "sum(rate(skill_api_calls_total[1m])) by (skill)", "legendFormat": "{{skill}}" }] } ] }17.3 与消息系统集成
Slack通知实现:
import slack_sdk def send_slack_notification(message): client = slack_sdk.WebClient(token=os.getenv('SLACK_TOKEN')) response = client.chat_postMessage( channel="#skill-notifications", text=message ) return response18. 技能质量评估体系
18.1 代码质量指标
SonarQube质量门禁:
qualitygate: conditions: - metric: coverage op: LT threshold: 80 error: true - metric: duplicated_lines_density op: GT threshold: 5 warning: true - metric: security_rating op: GT threshold: 1 error: true18.2 性能评估标准
性能评分算法:
def calculate_performance_score(response_time, throughput, error_rate): # 标准化各项指标 rt_score = max(0, 100 - response_time / 10) tp_score = min(100, throughput / 20) er_score = 100 - error_rate * 100 # 加权计算总分 return rt_score * 0.4 + tp_score * 0.5 + er_score * 0.118.3 用户体验评估
用户满意度调查:
def collect_feedback(skill_name): questions = [ { "text": "How easy was it to use this skill?", "options": ["Very easy", "Easy", "Neutral", "Difficult", "Very difficult"] }, { "text": "Did the skill meet your expectations?", "options": ["Exceeded", "Met",