Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Observação
Os auxiliares de auto-hospedagem para endpoints OpenAI Responses em .NET estão a chegar em breve.
Observação
Os auxiliares de auto-hospedagem para endpoints OpenAI Responses não estão atualmente disponíveis para o Go.
Utilize agent-framework-hosting-responses para converter pedidos e respostas com o formato de OpenAI Responses num endpoint controlado pela sua aplicação. O seu servidor escolhe o framework web, rota, autenticação, autorização, opções de pedido e armazenamento da sessão.
pip install --pre agent-framework agent-framework-foundry agent-framework-hosting agent-framework-hosting-responses azure-identity
A amostra do FastAPI é uma implementação. Os mesmos auxiliares funcionam com Django, Flask, Starlette, Funções do Azure ou outra estrutura.
Hospedar um ponto final de agente
Este exemplo converte o pedido para valores de execução do Agent Framework, aplica uma lista de opções definida pela aplicação e mantém a sessão atualizada sob o ID de resposta recém-criado.
app = FastAPI()
state = AgentState(
create_agent,
session_store=FileSessionStore(SESSIONS_DIR / "snapshots"),
)
ALLOWED_REQUEST_OPTIONS = frozenset({"max_tokens", "reasoning"})
@app.post("/responses", response_model=None)
async def responses(body: dict[str, Any] = Body(...)) -> JSONResponse | StreamingResponse: # noqa: B008
"""Handle one OpenAI Responses-shaped request."""
try:
run = responses_to_run(body)
except ValueError as exc:
raise HTTPException(status_code=400, detail=str(exc)) from exc
session_id, is_conversation_id = responses_session_id(body)
conversation_id = session_id if is_conversation_id else None
response_id = create_response_id()
# App-specific policy: allow only the request options this route is willing
# to honor. This denies tools, tool_choice, deployment/persistence fields,
# and all other caller-supplied options by default. Your app decides which
# options are allowed, altered, or denied.
options = {key: value for key, value in run["options"].items() if key in ALLOWED_REQUEST_OPTIONS}
options["reasoning"] = {"effort": "medium", "summary": "auto"}
options_for_run = cast(Any, options)
target = await state.get_target()
lookup_id = session_id or response_id
# An unknown id supplied through `conversation` becomes a new session here. Production apps
# can choose to require a separate "create conversation" API instead.
session = await state.get_or_create_session(lookup_id)
if run["stream"]:
stream = target.run(
run["messages"],
stream=True,
session=session,
options=options_for_run,
)
if not isinstance(stream, ResponseStream):
raise HTTPException(status_code=500, detail="agent did not return a response stream")
async def stream_events() -> AsyncIterator[str]:
async for event in responses_from_streaming_run(
stream,
response_id=response_id,
conversation_id=conversation_id,
):
yield event
# `agent.run(..., stream=True)` updates the session while the stream
# is consumed/finalized. Persist the selected continuation only
# after finalization.
if conversation_id is not None:
# A stable conversation id is a mutable head. Apps must ensure
# only one caller advances it at a time; AgentState does not
# serialize concurrent runs for the same id.
await state.set_session(conversation_id, session)
else:
await state.set_session(response_id, session)
return StreamingResponse(
stream_events(),
media_type="text/event-stream",
)
result = await target.run(
run["messages"],
session=session,
options=options_for_run,
)
# `agent.run(...)` updates the session. Persist the selected continuation
# only after the run completes.
AgentState resolve o alvo e carrega ou cria uma sessão. Guarda a sessão depois da execução, ou depois de uma execução em streaming terminar, porque a execução atualiza-a.
Para a aplicação completa, incluindo a definição do agente e a lista de opções de pedido permitidas, consulte o exemplo local do Responses.
Compreenda a conversão da utilização das respostas
Para as respostas de agentes e de fluxos de trabalho, o pacote de alojamento preserva inalterado um objeto OpenAI nativo ResponseUsage válido para o SDK, quando esse objeto está disponível. Não combina a utilização nativa de Responses com o Agent Framework UsageDetails.
Quando o uso nativo não está disponível, o pacote pode reconstruir o uso de Respostas a partir destes campos semanticamente correspondentes do Agent Framework:
| Valor de utilização | Campo Agent Framework |
|---|---|
| Tokens de entrada | input_token_count |
| Tokens de saída | output_token_count |
| Tokens de entrada lidos da cache | cache_read_input_token_count |
| Tokens de entrada para escrita na cache | cache_creation_input_token_count |
| Tokens de saída de raciocínio | reasoning_output_token_count |
Os valores nulos explícitos são preservados. Se total_tokens estiver ausente enquanto estiverem presentes tanto as contagens de entrada como de saída, o pacote deriva-o como entrada mais saída.
Se a utilização disponível do Agent Framework for incompleta ou semanticamente inconsistente com o esquema Responses, o pacote omite o uso. Não adivinha, não copia um contador para outro, nem faz falhar uma resposta que, de outro modo, teria êxito. Uma contagem escalar mal formada continua a ser um erro.
Esta reconstrução é deliberadamente com perdas, porque a utilização do Agent Framework é independente do fornecedor e a utilização do OpenAI Responses tem uma estrutura mais rica e específica de cada fornecedor. Contadores específicos do fornecedor reportados por um agente alojado, como o uso específico do Anthropic, podem não aparecer na resposta recebida pela aplicação que chama. Esta conversão não proporciona interoperabilidade entre diferentes versões do SDK OpenAI a correr no mesmo processo.
Alojar um endpoint de fluxo de trabalho
WorkflowState resolve o fluxo de trabalho, mas a sua aplicação é responsável pelo armazenamento do ponto de controlo e pelo mapeamento entre um ID de resposta e um ponto de controlo. Este exemplo restaura o ponto de controlo selecionado por um utilizador autorizado previous_response_id e, em seguida, guarda um cursor para a próxima resposta.
app = FastAPI()
state = WorkflowState(workflow_builder, cache_target=False)
@app.post("/responses", response_model=None)
async def responses(body: dict[str, Any] = Body(...)) -> JSONResponse: # noqa: B008
"""Handle one OpenAI Responses-shaped request for the workflow."""
try:
run = responses_to_run(body)
except ValueError as exc:
raise HTTPException(status_code=400, detail=str(exc)) from exc
# This sample demonstrates only Responses `previous_response_id`
# continuation, so reject `conversation` instead of treating it as a
# checkpoint cursor.
previous_response_id, is_conversation_id = responses_session_id(body)
if is_conversation_id:
raise HTTPException(
status_code=400,
detail="This server supports previous_response_id continuation only; conversation is not implemented.",
)
response_id = create_response_id()
target = await state.get_target()
if previous_response_id and (checkpoint_cursor := checkpoint_cursor_store.get(previous_response_id)) is not None:
# Restore first. Workflow.run does not allow `message` and
# `checkpoint_id` in the same call.
await target.run(
checkpoint_id=checkpoint_cursor["checkpoint_id"],
checkpoint_storage=checkpoint_storage_for(checkpoint_cursor["storage_id"]),
)
storage_id = response_id
checkpoint_storage = checkpoint_storage_for(storage_id)
result = await target.run(
message=workflow_prompt_from_messages(run["messages"]),
checkpoint_storage=checkpoint_storage,
)
latest = await checkpoint_storage.get_latest(workflow_name=target.name)
if latest is not None:
# Responses `previous_response_id` can point to any response id. Store
# the current response id as the cursor for this workflow continuation.
cursor = CheckpointCursor(checkpoint_id=latest.checkpoint_id, storage_id=storage_id)
checkpoint_cursor_store.set_many({response_id: cursor})
return JSONResponse(
responses_from_run(
response_from_workflow_result(result),
response_id=response_id,
)
)
O armazenamento baseado em ficheiros do exemplo destina-se ao desenvolvimento local. Use armazenamento durável quando as réplicas puderem reiniciar ou escalar.
Importante
Trata previous_response_id e conversation como input não confiável. Autentique e autorize o chamador antes de utilizar qualquer um dos dois valores para carregar ou guardar uma sessão ou um ponto de verificação. O campo legado do pedido conversation_id está obsoleto; use, em vez disso, o campo conversation do OpenAI Responses.
Para o formato de transmissão mais amplo, veja endpoints compatíveis com a OpenAI.
Passos seguintes
Vai mais fundo: