Skip to content

bithuman: cloud lane serves Expression 1 to an expression-2 agent (silent downgrade, billed as gen-1) #7077

Description

@A-I-M-O

Summary

The bitHuman cloud lane behind livekit-plugins-bithuman (POST auth.api.bithuman.ai/v1/runtime-tokens/request) serves Expression 1 to an agent whose only built model is expression-2 — a silent downgrade, billed at the Expression-1 rate. The docs for this lane promise the opposite.

Expected

Per the LiveKit deployment guide:

a second-generation agent serves its own model automatically … no model= kwarg is needed

And per models-v2, expression-2 is served on every cloud tier (GPU / ANE / CPU) and through every delivery surface including the LiveKit plugin.

Actual

Agent A57CQP1723 (Pro account) is built as expression-2 (model_status.expression-2.state: "ready"; supported_models: ["essence-2-max", "expression-2"]). No gen-1 model is built on it at all. Same agent, same account, same day:

lane billing_type video track face
bitHuman embed viewer usage_expression_2_model_cloud 416x720 renders correctly
runtime-tokens (this plugin's endpoint) usage_expression_model_cloud 512x512 featureless smear

The agent's stylized (non-photoreal) portrait is only renderable by Expression 2, so on this lane the face is destroyed — and the session bills 4.0 cr/min for the older engine vs 3.81 for Expression 2 on the viewer lane.

Note the launcher asymmetry: mode: "cpu" correctly refuses the agent (503: "that launcher serves essence-1 models, and this agent's available model(s) are: essence-2-max, expression-2"), while mode: "gpu" silently substitutes Expression 1 instead of refusing or serving expression-2.

Repro

POST https://auth.api.bithuman.ai/v1/runtime-tokens/request
headers: api-secret: <key>
json: {"livekit_url": ..., "livekit_token": <agent-kind token>,
       "room_name": ..., "mode": "gpu", "agent_id": "A57CQP1723"}

Worker joins and publishes 512x512; the account ledger (GET /v2/{user_id}/runtime-sessions) records billing_type: "usage_expression_model_cloud".

Ruled out

  • Extra body fields (model, model_version, billing_type) return 200 and are ignored; mode accepts only gpu/cpu.
  • Plugin v1.7.1 exposes no gen-2 selector (model: Literal["expression","essence"] only flips mode).
  • The plugin's exact JWT attribute set on the worker token (api_secret + agent_id + lk.publish_on_behalf, avatar.py L326–350) — tested, no change.
  • The model itself is fine: POST /v1/video/generate with model: "expression-2" renders the same agent flawlessly.

Ask

Serve expression-2 on the runtime-tokens lane for agents that have it built (as documented), or expose a parameter that selects it — or at minimum make the gpu launcher fail closed like the cpu launcher does, instead of silently downgrading and billing for it.

Happy to share room names, timestamps and session ids privately. (cc @sgu-bithuman)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions