跳转至

交互式聊天助手

将输入、流式回答和会话保存组合起来,得到一个可以连续对话的终端助手。

运行

完成模型配置,运行:

python examples/runtime/chat.py
"""流式聊天,/quit 退出;同一会话可以在下次运行继续。"""

import asyncio
import os

import bumblehive
from bumblehive.observability import MODEL_STREAM_CONTENT_DELTA


async def main() -> None:
    config = bumblehive.RuntimeArguments(
        model=os.environ["BUMBLEHIVE_MODEL"],
        api_key=os.environ["BUMBLEHIVE_API_KEY"],
        base_url=os.environ["BUMBLEHIVE_BASE_URL"],
        skill_names=[],
        tool_names=[],
    )
    async with bumblehive.from_config(config) as runtime:
        while True:
            text = (await asyncio.to_thread(input, "你:")).strip()
            if text == "/quit":
                break
            if not text:
                continue
            stream = runtime.stream(text, session_id="chat-example")
            print("Agent:", end="", flush=True)
            try:
                async for event in stream:
                    if event.kind == MODEL_STREAM_CONTENT_DELTA:
                        print(event.payload["delta"], end="", flush=True)
                result = await stream.result()
            finally:
                await stream.aclose()
            print()
            if result.error:
                print(result.error.message)


if __name__ == "__main__":
    asyncio.run(main())

体验对话

你:记住,我的项目叫 BumbleHive。
Agent:…确认项目名称…
你:我的项目叫什么?
Agent:你的项目叫 BumbleHive。
你:/quit

同一个 session_id 保留对话,stream() 逐段输出回答。重新运行程序会继续 chat-example 会话;修改 ID 可以开始新对话。

接入界面

把终端输入换成用户消息事件,把输出换成界面更新即可。下面的适配示例将文本和工具事件转换成 JSON 行:

python examples/runtime/chat_events.py
"""Map SDK events to small UI updates; print JSON lines as a transport example."""

import asyncio
import json
import os
from typing import Any

import bumblehive
from bumblehive.observability import (
    MODEL_STREAM_CONTENT_DELTA,
    TOOL_CALL_FINISHED,
    TOOL_CALL_STARTED,
)


def to_ui_update(event: bumblehive.AgentEvent) -> dict[str, Any] | None:
    update: dict[str, Any] = {"run_id": event.run_id, "session_id": event.session_id}
    if event.kind == MODEL_STREAM_CONTENT_DELTA:
        return {**update, "type": "text_delta", "text": event.payload["delta"]}
    if event.kind == TOOL_CALL_STARTED:
        call = event.payload["tool_call"]
        return {
            **update,
            "type": "tool_started",
            "call_id": call["call_id"],
            "name": call["name"],
        }
    if event.kind == TOOL_CALL_FINISHED:
        result = event.payload["tool_result"]
        return {
            **update,
            "type": "tool_finished",
            "call_id": result["tool_call_id"],
            "ok": event.payload["ok"],
        }
    return None


def send(update: dict[str, Any]) -> None:
    # A real application sends this update through its WebSocket or SSE layer.
    print(json.dumps(update, ensure_ascii=False), flush=True)


async def main() -> None:
    config = bumblehive.RuntimeArguments(
        model=os.environ["BUMBLEHIVE_MODEL"],
        api_key=os.environ["BUMBLEHIVE_API_KEY"],
        base_url=os.environ["BUMBLEHIVE_BASE_URL"],
        skill_names=[],
        tool_names=["add"],
    )
    async with bumblehive.from_config(config) as runtime:
        @runtime.tools.tool(name="add", description="计算两个整数的和。")
        def add(a: int, b: int) -> int:
            return a + b

        stream = runtime.stream("请调用 add 计算 21 加 34。", session_id="chat-events-demo")
        try:
            async for event in stream:
                update = to_ui_update(event)
                if update is not None:
                    send(update)
            result = await stream.result()
            send({
                "type": "finished",
                "text": result.final_content,
                "usage": result.usage,
                "error": result.error.message if result.error else None,
            })
        finally:
            await stream.aclose()


if __name__ == "__main__":
    asyncio.run(main())
更新 用途
text_delta 追加回答文本
tool_started 按 run_id 和 call_id 显示工具开始
tool_finished 更新同一个工具调用的结果
finished 显示最终回答或错误

需要人工参与时,接入审批、引导或追问。这些交互的实现集中在对应教程中。