Prompt Caching 与 AI 应用成本优化实战

作者:Maurice | 灵阙学院


背景:Token 是新的 CPU Cycle

AI 应用上线后,工程师面临的第一个生产问题往往不是性能,而是账单

一家做 AI 客服的 SaaS 公司,初期月调用量 200 万次,每次调用带入 3000 token 的系统提示词,使用 Claude Sonnet,月账单轻松突破 $5000。随着用户增长,这个数字线性放大——用户越多,亏得越快。

这不是个例。Token 定价模型决定了 AI 应用的成本结构与业务天花板:

月成本 = Σ (输入token数 × 输入单价 + 输出token数 × 输出单价) × 调用次数

与传统软件不同,AI 应用没有"写好一次代码永远运行"的免费边际成本——每次调用都要付钱。理解并控制 Token 消耗,是 AI 产品从 Demo 走向盈利的必修课。


第一章:AI 应用成本结构拆解

1.1 成本构成三要素

┌─────────────────────────────────────────────────────┐
│                AI 应用成本构成                        │
├──────────────────┬──────────────────────────────────┤
│  输入 Token      │  系统提示词 + 对话历史 + 用户消息  │
│  (Input Tokens)  │  通常占总 Token 的 60-85%         │
├──────────────────┼──────────────────────────────────┤
│  输出 Token      │  模型生成的回答内容                 │
│  (Output Tokens) │  单价通常是输入的 3-5x             │
├──────────────────┼──────────────────────────────────┤
│  调用次数        │  并发峰值决定基础架构成本            │
│  (API Calls)     │  Batch API 可显著降低              │
└──────────────────┴──────────────────────────────────┘

1.2 主流模型价格速查表(截至 2026 年 Q1)

模型 输入价格($/M tokens) 输出价格($/M tokens) 缓存后输入价格
Claude 3.5 Sonnet $3.00 $15.00 $0.30(缓存命中)
Claude 3.5 Haiku $0.80 $4.00 $0.08(缓存命中)
GPT-4o $2.50 $10.00 $1.25(自动缓存)
GPT-4o mini $0.15 $0.60 $0.075(自动缓存)
Gemini 2.0 Flash $0.10 $0.40 $0.025(上下文缓存)
Gemini 1.5 Pro $1.25 $5.00 $0.3125(上下文缓存)
DeepSeek V3 $0.27 $1.10 $0.014(硬盘缓存命中)
DeepSeek R1 $0.55 $2.19 $0.014(硬盘缓存命中)

注:价格随市场竞争持续下降,以官方 pricing 页面为准。缓存价格为典型场景估算。

1.3 成本分布的帕累托规律

实际监控数据显示,80% 的 Token 消耗来自:

  1. 系统提示词重复传输:每次对话都携带相同的角色设定、知识库、规则约束
  2. 长对话历史累积:多轮对话中历史消息线性增长
  3. RAG 检索内容冗余:每次检索到相似的文档片段重复传输

这三类场景,恰好是 Prompt Caching 的核心战场。


第二章:Prompt Caching 核心原理

2.1 KV-Cache 工作机制

Transformer 模型处理输入时,会为每个 token 计算 Key-Value 向量对,这个计算过程占据推理成本的主体。Prompt Caching 的本质是将前缀 token 的 KV 向量缓存在服务器内存中,后续请求匹配相同前缀时直接复用,跳过重复计算。

┌─────────────────────────────────────────────────────────┐
│                  KV-Cache 工作流程                        │
│                                                          │
│  第一次请求:                                             │
│  [系统提示词 3000 tokens] + [用户消息 50 tokens]          │
│       ↓ 全量计算 KV                                      │
│  [KV-Cache 存入服务器内存] + [生成回答]                   │
│                                                          │
│  第二次请求(相同前缀):                                   │
│  [系统提示词 3000 tokens] ← 命中缓存,跳过计算             │
│       + [用户消息 80 tokens] ← 仅计算新增部分              │
│       ↓ 仅需计算 80 tokens 的 KV                         │
│  节省计算 = 3000 / 3080 ≈ 97%                            │
└─────────────────────────────────────────────────────────┘

关键约束:缓存匹配要求精确前缀匹配。只要前缀内容或顺序发生变化(哪怕一个空格),缓存即失效。这决定了缓存友好型 Prompt 的设计原则:把静态内容放前面,动态内容放后面

2.2 三大厂商实现对比

维度 Anthropic OpenAI Google
触发方式 显式标记 cache_control 自动前缀匹配 显式创建缓存对象
输入成本折扣 命中节省 90%(缓存写入+10%) 命中节省 50% 命中节省 75-80%
TTL 5 分钟(最长 1 小时) 5-10 分钟 自定义(最长 24 小时)
最小缓存 Token 1024 tokens 1024 tokens 32768 tokens
是否需改代码 需要(加 cache_control 字段) 不需要 需要(调用缓存 API)
适合场景 精准控制缓存边界 零成本接入 超长系统提示词

DeepSeek 的差异化方案

DeepSeek 采用**硬盘缓存(Disk Cache)**而非内存缓存,TTL 可达数天,适合极低成本场景。其缓存命中价格约 $0.014/M tokens,是目前市场最低,但响应延迟略高于内存缓存方案。


第三章:代码实战

3.1 Anthropic Claude — 显式 cache_control

import anthropic

client = anthropic.Anthropic()

# 将静态系统提示词标记为可缓存
SYSTEM_PROMPT = """你是一个专业的财税合规顾问,熟悉中国企业会计准则(CAS)、
增值税(VAT)申报流程、企业所得税(CIT)优惠政策及跨境税务处理规则。

[此处可放置 2000+ token 的专业知识库内容]
...
"""

def ask_tax_question(user_question: str, conversation_history: list) -> str:
    response = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=1024,
        system=[
            {
                "type": "text",
                "text": SYSTEM_PROMPT,
                "cache_control": {"type": "ephemeral"}  # 标记为可缓存
            }
        ],
        messages=[
            # 历史对话也可缓存(标记最后一条历史消息)
            *[
                {
                    "role": msg["role"],
                    "content": [
                        {
                            "type": "text",
                            "text": msg["content"],
                            # 仅对历史消息中最后一条加缓存标记
                            **({"cache_control": {"type": "ephemeral"}}
                               if i == len(conversation_history) - 1 else {})
                        }
                    ]
                }
                for i, msg in enumerate(conversation_history)
            ],
            {"role": "user", "content": user_question}
        ]
    )

    # 从响应头检查缓存使用情况
    usage = response.usage
    cache_read = getattr(usage, 'cache_read_input_tokens', 0)
    cache_write = getattr(usage, 'cache_creation_input_tokens', 0)

    print(f"Token 使用: 输入={usage.input_tokens}, 输出={usage.output_tokens}")
    print(f"缓存命中: {cache_read} tokens, 缓存写入: {cache_write} tokens")

    if cache_read > 0:
        savings = cache_read * 0.9  # 节省 90% 的命中 token 成本
        print(f"本次节省约: {savings:.0f} token 当量的费用")

    return response.content[0].text

关键细节

  • cache_control 标记在消息内容块级别,不是消息级别
  • 系统提示词必须超过 1024 tokens 才会触发缓存
  • 缓存写入会有 25% 的额外写入成本,但第二次起即回本
  • 同一会话内 TTL 为 5 分钟,高频对话需注意请求间隔

3.2 OpenAI — 零代码自动缓存

from openai import OpenAI

client = OpenAI()

# OpenAI 自动缓存:无需任何代码改动
# 只需确保 system prompt 前缀一致即可

SYSTEM_PROMPT = "你是一个专业助手..." * 100  # 确保超过 1024 tokens

def ask_with_auto_cache(user_message: str) -> str:
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": user_message}
        ]
    )

    # 检查缓存命中情况
    usage = response.usage
    if hasattr(usage, 'prompt_tokens_details'):
        cached = usage.prompt_tokens_details.cached_tokens
        print(f"缓存命中 tokens: {cached}")
        if cached > 0:
            print(f"节省约 50% 的命中 token 费用")

    return response.choices[0].message.content

OpenAI 自动缓存的注意事项

  • 前缀必须完全相同才能命中,包括空格和换行符
  • 不支持手动控制缓存范围,模型自动判断缓存边界
  • 适合 system prompt 固定、用户消息变化的标准 Chat 场景

3.3 Google Gemini — 显式缓存对象

import google.generativeai as genai
from google.generativeai import caching
import datetime

genai.configure(api_key="YOUR_API_KEY")

# 创建显式缓存(适合超长 system prompt,最小 32768 tokens)
LONG_SYSTEM_PROMPT = "..." * 5000  # 超过 32K token 的知识库内容

# 一次性创建缓存(可跨多个请求复用)
cache = caching.CachedContent.create(
    model="models/gemini-1.5-pro-002",
    display_name="tax_knowledge_base",
    system_instruction=LONG_SYSTEM_PROMPT,
    ttl=datetime.timedelta(hours=2),  # 自定义 TTL,最长 24 小时
)

print(f"缓存创建成功: {cache.name}")
print(f"缓存过期时间: {cache.expire_time}")

# 使用缓存创建模型实例
model = genai.GenerativeModel.from_cached_content(cached_content=cache)

# 后续所有请求自动使用缓存,无需重复传输 system prompt
response = model.generate_content("增值税专用发票的抵扣期限是多少?")
print(response.text)

# 用完后可手动删除缓存节省存储成本
cache.delete()

3.4 缓存友好型 Prompt 结构设计

┌─────────────────────────────────────────────────────────┐
│            缓存友好的 Prompt 结构(正确做法)              │
│                                                          │
│  [STATIC - 缓存区]                                       │
│  ┌─────────────────────────────────────────────────┐    │
│  │ 角色设定(Role Definition)                       │    │
│  │ 能力边界(Capability Scope)                      │    │
│  │ 行为规则(Behavioral Rules)                      │    │
│  │ 知识库内容(Knowledge Base - RAG 结果提前放入)    │    │
│  │ 输出格式规范(Output Format Spec)                 │    │
│  └─────────────────────────────────────────────────┘    │
│       ↑ cache_control 标记在此处 ↑                       │
│                                                          │
│  [DYNAMIC - 非缓存区]                                    │
│  ┌─────────────────────────────────────────────────┐    │
│  │ 当前对话历史(Recent Conversation)               │    │
│  │ 用户当前消息(Current User Message)              │    │
│  │ 实时上下文(Timestamp, User ID 等)               │    │
│  └─────────────────────────────────────────────────┘    │
│                                                          │
│  反模式(会破坏缓存):                                    │
│  - 在系统提示词中插入时间戳:{{current_time}}             │
│  - 动态拼接用户名到前缀:f"你好 {username},你是..."       │
│  - 每次调用随机化 few-shot 示例顺序                        │
└─────────────────────────────────────────────────────────┘

第四章:五大成本优化策略

策略一:Prompt Caching(必选,优先实施)

适用场景:系统提示词 > 1024 tokens,调用频率 > 每 5 分钟一次

实施路径

  1. 审计现有 Prompt,将静态内容提取到前缀
  2. 移除前缀中的动态变量(时间戳、用户名等)
  3. 添加 cache_control 标记(Anthropic)或验证前缀一致性(OpenAI)
  4. 监控 cache_read_input_tokens 指标,确认命中率

预期收益:系统提示词占比越高,收益越大。典型场景下可降低输入成本 60-85%。

策略二:模型路由(按任务复杂度分级)

不是所有任务都需要 GPT-4o 或 Claude Sonnet。建立任务分类路由规则:

def route_model(task_type: str, context_length: int) -> str:
    """根据任务复杂度路由到合适的模型"""
    if task_type in ["keyword_extraction", "classification", "simple_qa"]:
        # 简单任务:使用小模型,成本降低 10-20x
        return "claude-3-5-haiku-20241022"  # $0.8/M vs $3/M

    elif task_type in ["summarization", "translation", "structured_output"]:
        # 中等任务:平衡模型
        return "gpt-4o-mini"  # $0.15/M

    elif task_type in ["complex_reasoning", "code_generation", "analysis"]:
        # 复杂任务:旗舰模型
        return "claude-3-5-sonnet-20241022"

    # 超长上下文:专用模型
    elif context_length > 100000:
        return "gemini-1.5-pro-002"  # 长上下文专家

    return "claude-3-5-sonnet-20241022"  # 默认旗舰

成本对比:同等任务量,精准路由可降低总成本 40-70%。

策略三:输出 Token 控制

输出 token 单价通常是输入的 3-5 倍,控制输出长度是高杠杆优化点。

# 方法 1:显式设置 max_tokens
response = client.messages.create(
    model="claude-3-5-sonnet-20241022",
    max_tokens=512,  # 明确限制,避免模型"话痨"
    messages=[{"role": "user", "content": user_input}]
)

# 方法 2:结构化输出限制格式(强迫模型使用 JSON,减少废话)
SYSTEM = """请以 JSON 格式回答,格式如下:
{"answer": "核心答案(50字以内)", "confidence": "high|medium|low", "source": "依据"}
不要包含任何解释性文字。"""

# 方法 3:在 Prompt 中明确长度要求
SYSTEM = "回答必须在 3 句话以内,直接给出结论,不要展开分析。"

实际效果:合理的 max_tokens 设置可将输出 token 消耗降低 30-50%,且通常不影响回答质量。

策略四:批处理 API

对于非实时性任务(报告生成、数据分析、内容审核),批处理 API 提供 50% 折扣:

# OpenAI Batch API 示例
import json
from openai import OpenAI

client = OpenAI()

# 准备批处理任务
requests = [
    {
        "custom_id": f"request-{i}",
        "method": "POST",
        "url": "/v1/chat/completions",
        "body": {
            "model": "gpt-4o",
            "messages": [
                {"role": "system", "content": SYSTEM_PROMPT},
                {"role": "user", "content": user_questions[i]}
            ],
            "max_tokens": 500
        }
    }
    for i in range(len(user_questions))
]

# 提交批处理(24小时内完成,成本降低 50%)
batch_input_file = client.files.create(
    file=("\n".join(json.dumps(r) for r in requests)).encode(),
    purpose="batch"
)

batch = client.batches.create(
    input_file_id=batch_input_file.id,
    endpoint="/v1/chat/completions",
    completion_window="24h"
)

print(f"批处理任务已提交: {batch.id}")

Anthropic Message Batches 提供相同的 50% 折扣,API 风格类似,适合 Claude 用户。

策略五:语义缓存

相似问题直接返回历史答案,彻底绕过 LLM 调用:

from sentence_transformers import SentenceTransformer
import numpy as np
import redis
import json

class SemanticCache:
    def __init__(self, similarity_threshold: float = 0.92):
        self.encoder = SentenceTransformer("BAAI/bge-small-zh-v1.5")
        self.redis = redis.Redis()
        self.threshold = similarity_threshold

    def get_or_generate(self, question: str, generate_fn) -> str:
        # 编码当前问题
        query_embedding = self.encoder.encode(question)

        # 搜索相似历史问题(实际项目用向量数据库如 Qdrant/Milvus)
        cached_keys = self.redis.keys("cache:*")
        for key in cached_keys:
            cached_data = json.loads(self.redis.get(key))
            similarity = np.dot(query_embedding, cached_data["embedding"])
            if similarity > self.threshold:
                print(f"语义缓存命中!相似度: {similarity:.3f}")
                return cached_data["answer"]

        # 未命中,调用 LLM
        answer = generate_fn(question)

        # 存入缓存
        cache_key = f"cache:{hash(question)}"
        self.redis.setex(
            cache_key,
            3600,  # 1小时 TTL
            json.dumps({
                "question": question,
                "embedding": query_embedding.tolist(),
                "answer": answer
            })
        )
        return answer

适用场景:FAQ 类应用、客服机器人、知识库问答。命中率达到 30-40% 时,整体成本可降低 25-35%。


第五章:成本监控体系

5.1 每请求成本追踪

from dataclasses import dataclass
from datetime import datetime

# 模型定价配置(单位:美元/百万 tokens)
MODEL_PRICING = {
    "claude-3-5-sonnet-20241022": {
        "input": 3.00, "output": 15.00,
        "cache_write": 3.75, "cache_read": 0.30
    },
    "gpt-4o": {
        "input": 2.50, "output": 10.00,
        "cache_read": 1.25
    },
}

@dataclass
class RequestCost:
    model: str
    input_tokens: int
    output_tokens: int
    cache_read_tokens: int
    cache_write_tokens: int
    user_id: str
    feature: str
    timestamp: datetime

    @property
    def total_cost_usd(self) -> float:
        pricing = MODEL_PRICING.get(self.model, {})
        regular_input = self.input_tokens - self.cache_read_tokens
        cost = (
            regular_input * pricing.get("input", 0) / 1_000_000
            + self.output_tokens * pricing.get("output", 0) / 1_000_000
            + self.cache_read_tokens * pricing.get("cache_read", 0) / 1_000_000
            + self.cache_write_tokens * pricing.get("cache_write", 0) / 1_000_000
        )
        return cost

def track_request_cost(response, user_id: str, feature: str) -> RequestCost:
    usage = response.usage
    cost = RequestCost(
        model=response.model,
        input_tokens=usage.input_tokens,
        output_tokens=usage.output_tokens,
        cache_read_tokens=getattr(usage, 'cache_read_input_tokens', 0),
        cache_write_tokens=getattr(usage, 'cache_creation_input_tokens', 0),
        user_id=user_id,
        feature=feature,
        timestamp=datetime.utcnow()
    )
    # 写入数据库或监控系统
    store_cost_metric(cost)
    return cost

5.2 监控 Dashboard 设计

┌────────────────────────────────────────────────────────────┐
│              AI 成本监控 Dashboard                           │
├────────────────┬───────────────┬───────────────────────────┤
│  今日总成本     │  本月总成本    │  预估月末成本               │
│  $127.40       │  $2,847.20   │  $4,230.00                 │
├────────────────┴───────────────┴───────────────────────────┤
│  缓存效率                                                    │
│  缓存命中率: 73%  |  节省成本: $891/月  |  总调用: 284,720   │
├────────────────────────────────────────────────────────────┤
│  按功能成本归因(本月)                                        │
│  智能问答        ████████████████ $1,241 (43.6%)           │
│  报告生成        ████████         $687  (24.1%)            │
│  内容审核        █████            $421  (14.8%)            │
│  数据分析        ████             $312  (11.0%)            │
│  其他           ██               $186  (6.5%)             │
├────────────────────────────────────────────────────────────┤
│  异常告警                                                    │
│  [WARN] user_id=u_3847 本日成本 $23.40,超过阈值 $10        │
│  [INFO] 缓存命中率下降 12%,请检查系统提示词是否变更           │
└────────────────────────────────────────────────────────────┘

5.3 异常检测规则

# 成本异常告警规则
ALERT_RULES = [
    # 单用户超额
    {"type": "per_user_daily", "threshold_usd": 10.0, "action": "notify_admin"},
    # 单次请求超额(可能是 Prompt 注入或异常输入)
    {"type": "per_request", "threshold_usd": 0.50, "action": "log_and_flag"},
    # 整体日成本异常(同比前一周)
    {"type": "daily_vs_last_week", "threshold_ratio": 1.5, "action": "alert_slack"},
    # 缓存命中率异常下降
    {"type": "cache_hit_rate", "threshold_ratio": 0.8, "action": "alert_oncall"},
]

第六章:真实案例 — 从月 $5000 到 $800 的优化路径

背景

某 SaaS 产品:AI 驱动的财税合规顾问,月活用户 800 人,平均每用户每天 8 次对话。

初始状态

  • 模型:Claude Sonnet(所有场景统一使用)
  • 系统提示词:4500 tokens,每次调用重新传输
  • 无缓存,无路由,无批处理
  • 月账单:$5,127

优化过程

Week 1:启用 Prompt Caching
─────────────────────────────
操作:为 4500 token 系统提示词添加 cache_control
结果:缓存命中率 81%,输入成本降低 72%
月账单:$5,127 → $2,890 (节省 $2,237)

Week 2:实施模型路由
─────────────────────────────
操作:将简单 FAQ(占 45% 调用量)路由到 Haiku
结果:Haiku 成本约为 Sonnet 的 1/4
月账单:$2,890 → $1,840 (节省 $1,050)

Week 3:部署语义缓存
─────────────────────────────
操作:对高频问题启用语义缓存(命中率 28%)
结果:28% 的请求直接返回缓存,零 LLM 成本
月账单:$1,840 → $1,210 (节省 $630)

Week 4:批处理迁移
─────────────────────────────
操作:将月报生成、数据分析迁移到 Batch API
结果:批处理任务量占成本 35%,享受 50% 折扣
月账单:$1,210 → $1,010 (节省 $200)

Month 2:精细化 max_tokens 控制
─────────────────────────────
操作:按场景设定合理的 max_tokens 上限
结果:输出 token 平均减少 34%
月账单:$1,010 → $800 (节省 $210)

最终结果:月账单从 $5,127 降至 $800,降幅 84%,且用户体验未受影响。

关键经验

  1. Prompt Caching 是成本最高的单一优化手段,应优先实施
  2. 模型路由需要任务分类能力,前期需要一定的工程投入
  3. 语义缓存在垂直领域效果显著,FAQ 类应用命中率可达 40%+
  4. 监控先于优化,没有可见性就无法做决策

第七章:成本计算速查公式

单次调用成本

cost = (input_tokens × input_price
      + output_tokens × output_price
      + cache_read_tokens × cache_read_price
      + cache_write_tokens × cache_write_price) / 1,000,000

月成本估算(含缓存)

月成本 = 月总调用次数 × [
    (系统提示词 tokens × (1 - 缓存命中率) × 输入单价
     + 系统提示词 tokens × 缓存命中率 × 缓存命中单价
     + 平均用户消息 tokens × 输入单价
     + 平均输出 tokens × 输出单价)
] / 1,000,000

缓存 ROI 计算

月节省 = 月总调用次数 × 系统提示词 tokens × 缓存命中率
         × (输入单价 - 缓存命中单价) / 1,000,000

缓存回本时间 = 首次缓存写入成本 / 每次节省额
             ≈ 第 2 次请求即回本(Anthropic 场景)

快速估算工具

def estimate_monthly_cost(
    monthly_calls: int,
    system_prompt_tokens: int,
    avg_user_tokens: int,
    avg_output_tokens: int,
    cache_hit_rate: float,
    model: str = "claude-3-5-sonnet-20241022"
) -> dict:
    pricing = MODEL_PRICING[model]

    uncached_input = (
        monthly_calls * system_prompt_tokens * (1 - cache_hit_rate)
        * pricing["input"] / 1_000_000
    )
    cached_input = (
        monthly_calls * system_prompt_tokens * cache_hit_rate
        * pricing["cache_read"] / 1_000_000
    )
    user_input = monthly_calls * avg_user_tokens * pricing["input"] / 1_000_000
    output = monthly_calls * avg_output_tokens * pricing["output"] / 1_000_000

    total = uncached_input + cached_input + user_input + output

    return {
        "monthly_cost_usd": round(total, 2),
        "uncached_input_cost": round(uncached_input, 2),
        "cached_input_cost": round(cached_input, 2),
        "output_cost": round(output, 2),
        "cache_savings_ratio": f"{cache_hit_rate * 0.9 * 100:.0f}% 输入成本节省"
    }

# 示例:月调用 10 万次,4500 token 系统提示词,50 token 用户消息,200 token 输出
result = estimate_monthly_cost(
    monthly_calls=100_000,
    system_prompt_tokens=4500,
    avg_user_tokens=50,
    avg_output_tokens=200,
    cache_hit_rate=0.80,
    model="claude-3-5-sonnet-20241022"
)
print(result)
# 输出示例:{'monthly_cost_usd': 587.50, 'cache_savings_ratio': '72% 输入成本节省'}

总结:AI 成本优化优先级矩阵

优化策略 实施难度 成本降幅 优先级 适合场景
Prompt Caching 60-85% P0 必选 固定系统提示词 > 1024 tokens
模型路由 40-70% P1 优先 多样化任务类型
max_tokens 控制 20-40% P1 优先 输出过长的场景
批处理 API 50% P2 推荐 非实时任务
语义缓存 20-35% P2 推荐 FAQ、垂直领域问答
成本监控 间接 P0 必选 所有 AI 应用

行动建议

  1. 本周:部署成本监控,建立基线数据
  2. 第 2 周:启用 Prompt Caching,这是单一最高 ROI 的优化
  3. 第 3-4 周:实施模型路由和 max_tokens 控制
  4. 第 2 个月:评估批处理和语义缓存的适用性

AI 的成本优化没有银弹,但有清晰的优先级。从监控开始,从 Caching 起步,用数据驱动决策——这是 AI 产品从烧钱到盈利的必经之路。


Maurice | maurice_wen@proton.me