AI 工具

用 Jasper Brand Voice 校验器检查语气配置

Jasper 的 Brand Voice(API 里 tones)靠一段可执行的语气描述。这篇在调用 POST /v1/tones 前,用 voicebrief.py 检查 name/value/metadata 是否齐全、是否过短,并挡掉明显的冒充类提示词。

BINBHO · 图文教程

Jasper 的 Brand Voice(API 里 tones)靠一段可执行的语气描述。这篇在调用 POST /v1/tones 前,用 voice_brief.py 检查 name/value/metadata 是否齐全、是否过短,并挡掉明显的冒充类提示词。

先看清成品

  • sample_ok 返回 OK;sample_bad 报告 name/过短/metadata 键数。
  • 3 项 pytest 通过。

合规提醒:Jasper API 需工作区管理员/开发者权限开通;密钥勿进前端或公开仓库。生成营销文案须遵守广告与行业法规,禁止虚假疗效、保证收益等表述。品牌声音与知识库应使用你有权使用的资料。价格与套餐以官网为准,本文不编造。

运行说明:无 Jasper 正式密钥。A/C 为本地校验;B 用本机 mock(X-API-Key)跑通创建 tone + run task。2026-10-23(Asia/Shanghai)pytest 全部通过。对接正式环境时把 --base 设为 https://api.jasper.ai 。

做完之后你会得到什么?

成果 说明
voice_brief.py 校验器
sample_ok.json / sample_bad.json 样例
test_97a.py 3 项测试

需要准备哪些环境?

项目 说明
Python 3.10+ 标准库 + pytest

关键事实

事实 来源
创建 voice 需 name 与 value;metadata 最多 10 键,键≤40、值≤500 字符 官方 Create a voice
请求头使用 X-API-Key 官方 Authentication
本校验器的 value 最短长度是教程启发式,便于写出可操作描述 实践

文件结构

97-jasper-A-src/
├── voice_brief.py
├── sample_ok.json
├── sample_bad.json
└── test_97a.py

第 1 步:校验脚本

#!/usr/bin/env python3
"""Validate a Jasper Brand Voice brief before POST /v1/tones."""
from __future__ import annotations

import argparse
import json
import re
from pathlib import Path

# Soft limits aligned with practical API usage (official create tone: name + value required;
# metadata up to 10 keys, key<=40, value<=500 per Jasper docs).
NAME_MAX = 80
VALUE_MIN = 40
VALUE_MAX = 4000
META_MAX_KEYS = 10
META_KEY_MAX = 40
META_VAL_MAX = 500


def validate(brief: dict) -> list[str]:
    errs: list[str] = []
    name = (brief.get("name") or "").strip()
    value = (brief.get("value") or "").strip()
    if not name:
        errs.append("name 必填")
    elif len(name) > NAME_MAX:
        errs.append(f"name 过长(>{NAME_MAX})")
    if not value:
        errs.append("value(声音描述)必填")
    else:
        if len(value) < VALUE_MIN:
            errs.append(f"value 过短(<{VALUE_MIN}),品牌声音需要可操作的语气说明")
        if len(value) > VALUE_MAX:
            errs.append(f"value 过长(>{VALUE_MAX})")
        if not re.search(r"[\u4e00-\u9fffA-Za-z]", value):
            errs.append("value 似乎没有可读文字")
    meta = brief.get("metadata") or {}
    if meta is not None and not isinstance(meta, dict):
        errs.append("metadata 必须是对象")
    elif isinstance(meta, dict):
        if len(meta) > META_MAX_KEYS:
            errs.append(f"metadata 键数 > {META_MAX_KEYS}")
        for k, v in meta.items():
            if len(str(k)) > META_KEY_MAX:
                errs.append(f"metadata 键过长: {k}")
            if len(str(v)) > META_VAL_MAX:
                errs.append(f"metadata 值过长: {k}")
    # discourage impersonation / fake authority
    bad = ("冒充", "伪造官方", "假装是", "undisclosed paid", "fake review")
    low = value.lower()
    for b in bad:
        if b.lower() in low or b in value:
            errs.append(f"疑似不当用途提示词: {b}")
    return errs


def main(argv=None) -> int:
    ap = argparse.ArgumentParser(description=__doc__)
    ap.add_argument("brief_json")
    args = ap.parse_args(argv)
    brief = json.loads(Path(args.brief_json).read_text(encoding="utf-8"))
    errs = validate(brief)
    if errs:
        print("INVALID")
        for e in errs:
            print("-", e)
        return 1
    print("OK")
    print(json.dumps({"name": brief["name"], "value_len": len(brief["value"].strip())}, ensure_ascii=False))
    return 0


if __name__ == "__main__":
    raise SystemExit(main())

第 2 步:测试

from pathlib import Path
import json
import subprocess
import sys
from voice_brief import validate

HERE = Path(__file__).resolve().parent


def test_ok():
    brief = json.loads((HERE / "sample_ok.json").read_text())
    assert validate(brief) == []


def test_bad():
    brief = json.loads((HERE / "sample_bad.json").read_text())
    errs = validate(brief)
    assert any("name" in e for e in errs)
    assert any("过短" in e for e in errs)
    assert any("键数" in e for e in errs)


def test_cli_ok():
    r = subprocess.run(
        [sys.executable, str(HERE / "voice_brief.py"), str(HERE / "sample_ok.json")],
        capture_output=True,
        text=True,
    )
    assert r.returncode == 0
    assert "OK" in r.stdout

第 3 步:运行

OK
{"name": "Acme 专业稳重", "value_len": 63}
...                                                                      [100%]
3 passed in 0.03s

# bad:
INVALID
- name 必填
- value 过短(<40),品牌声音需要可操作的语气说明
- metadata 键数 > 10

怎么检查结果?

  • OK 时打印 value_len。
  • 正式创建前再人工读一遍 value。

调试示例

value 太文学、不可执行。 「专业、有温度」不够;要写称呼、句长、禁用词、产品名大小写。校验器只保证长度与结构,不能代替品牌手册。

常见问题

现象 原因 处理
官方限制不同 文档更新 以 developers.jasper.ai 为准
要批量导入 CSV→JSON 逐条 validate
误报冒充 词表 按团队政策改 bad 列表

模板规则

  • 密钥不进仓库。
  • 声音描述避免冒充真人/官方。
  • 不编造套餐价。

项目资源

用途 地址
Authentication(官方) https://developers.jasper.ai/docs/authentication
Create a voice(官方) https://developers.jasper.ai/reference/createtone
Jasper 官网 https://www.jasper.ai/

先把声音说明写清楚,再交给 API。