|
| 1 | +"""两个 Identity 共用一个 Template,写入各自的个性化配置,再读取生效配置并在会话中验证。 |
| 2 | +
|
| 3 | +运行:python -m examples.forward.identity_config |
| 4 | +""" |
| 5 | + |
| 6 | +from __future__ import annotations |
| 7 | + |
| 8 | +from examples.common.live import Run, choose_model, marker, name, run_cli |
| 9 | +from qca import Forward |
| 10 | + |
| 11 | +from ._cleanup import finish_session |
| 12 | + |
| 13 | + |
| 14 | +def run(client: Forward, context: Run) -> None: |
| 15 | + environment = client.environments.create(name=name("env"), config={"type": "cloud"}) |
| 16 | + environment_id = context.track("environment", environment.id, lambda: client.environments.archive(environment.id)) |
| 17 | + |
| 18 | + model = choose_model(client.models.list(), context.config.model) |
| 19 | + context.output("selected_model", model) |
| 20 | + shared, baseline = marker(), marker() |
| 21 | + template = client.templates.create( |
| 22 | + name=name("template"), |
| 23 | + environment_id=environment_id, |
| 24 | + model=model, |
| 25 | + system="你是一个 SDK 示例助手。必要时调用工具,只使用可实际读取的数据回答问题。", |
| 26 | + tools=[{"type": "agent_toolset_20260401"}], |
| 27 | + environment_variables={"SDK_SHARED_VALUE": shared, "SDK_PERSONAL_VALUE": baseline}, |
| 28 | + ) |
| 29 | + template_id = context.track("template", template.id, lambda: client.templates.archive(template.id)) |
| 30 | + |
| 31 | + # 先创建两个 Identity 并写入个性化配置:SDK_SHARED_VALUE 继承模板默认,SDK_PERSONAL_VALUE 被各自覆盖。 |
| 32 | + identities: list[str] = [] |
| 33 | + personal: list[str] = [] |
| 34 | + for index in range(2): |
| 35 | + identity = client.identities.create(external_id=name("identity"), name=f"SDK 示例用户 {index + 1}") |
| 36 | + identity_id = context.track("identity", identity.id, lambda ref=identity.id: client.identities.delete(ref)) |
| 37 | + identities.append(identity_id) |
| 38 | + value = marker() |
| 39 | + personal.append(value) |
| 40 | + client.identities.configs.upsert( |
| 41 | + template_id, |
| 42 | + identity_id=identity_id, |
| 43 | + identity_config={"environment_variables": {"SDK_PERSONAL_VALUE": {"op": "set", "value": value}}}, |
| 44 | + ) |
| 45 | + effective = client.identities.configs.retrieve_effective(template_id, identity_id=identity_id) |
| 46 | + context.output( |
| 47 | + f"identity_{index + 1}_effective_env", |
| 48 | + effective.session.environment_variables if effective.session else None, |
| 49 | + ) |
| 50 | + |
| 51 | + # 每个 Identity 各起一个会话,读取自己实际生效的环境变量。 |
| 52 | + for index, identity_id in enumerate(identities): |
| 53 | + session = client.sessions.create(identity_id=identity_id, template_id=template_id) |
| 54 | + session_id = context.track("session", session.id, lambda ref=session.id: finish_session(client, context, ref)) |
| 55 | + prompt = "请使用工具读取 SDK_SHARED_VALUE 和 SDK_PERSONAL_VALUE 两个环境变量,只返回这两个变量的实际值。" |
| 56 | + context.output(f"identity_{index + 1}_user", prompt) |
| 57 | + sent = client.sessions.events.send( |
| 58 | + session_id, |
| 59 | + events=[{"type": "user.message", "content": [{"type": "text", "text": prompt}]}], |
| 60 | + extra_headers={"Idempotency-Key": name("event")}, |
| 61 | + ) |
| 62 | + if not sent.data or not sent.data[0].id: |
| 63 | + raise RuntimeError("Send returned no user event") |
| 64 | + with client.sessions.events.stream( |
| 65 | + session_id, |
| 66 | + extra_headers={"Last-Event-ID": sent.data[0].id}, |
| 67 | + timeout=context.remaining(), |
| 68 | + ) as stream: |
| 69 | + for event in stream: |
| 70 | + context.remaining() |
| 71 | + if event.type == "agent.message": |
| 72 | + context.output(f"identity_{index + 1}_assistant", event.to_json()) |
| 73 | + elif event.type in ("session.error", "session.status_terminated"): |
| 74 | + raise RuntimeError(f"Session stopped: {event.type}") |
| 75 | + elif event.type == "session.status_idle": |
| 76 | + break |
| 77 | + |
| 78 | + |
| 79 | +if __name__ == "__main__": |
| 80 | + run_cli("forward", Forward, {"identity_config": run}) |
0 commit comments