test(fase2): gated live local + Foundry profile checks
This commit is contained in:
parent
156df15417
commit
308b5539e2
2 changed files with 66 additions and 0 deletions
27
tests/test_foundry_profile_live.py
Normal file
27
tests/test_foundry_profile_live.py
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
"""Step 14 — GATED live Foundry-profile check (trivial response on the cheapest model, D6).
|
||||||
|
|
||||||
|
NOT default CI: skips cleanly without a configured Foundry endpoint + deployment. When set, a
|
||||||
|
trivial agent responds on a real FoundryChatClient (cheapest model, hard-capped per D6).
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from agent_framework import Agent
|
||||||
|
|
||||||
|
from portfolio_optimiser.backends import AzureFoundryBackend
|
||||||
|
|
||||||
|
_ENDPOINT = os.environ.get("PORTFOLIO_FOUNDRY_PROJECT_ENDPOINT")
|
||||||
|
_DEPLOYMENT = os.environ.get("PORTFOLIO_FOUNDRY_DEPLOYMENT")
|
||||||
|
_NO_FOUNDRY = not (_ENDPOINT and _DEPLOYMENT)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
_NO_FOUNDRY,
|
||||||
|
reason="Foundry not configured (set PORTFOLIO_FOUNDRY_PROJECT_ENDPOINT + PORTFOLIO_FOUNDRY_DEPLOYMENT)",
|
||||||
|
)
|
||||||
|
async def test_foundry_profile_trivial_response() -> None:
|
||||||
|
client = AzureFoundryBackend().create_chat_client(model=_DEPLOYMENT) # type: ignore[arg-type]
|
||||||
|
agent = Agent(client, "Answer in exactly one word.", name="probe")
|
||||||
|
result = await agent.run("Reply with the single word OK.")
|
||||||
|
assert getattr(result, "text", "") # a trivial response came back
|
||||||
39
tests/test_local_profile_live.py
Normal file
39
tests/test_local_profile_live.py
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
"""Step 14 — GATED live local-profile check (real UsageDetails + loopback-only no-egress).
|
||||||
|
|
||||||
|
NOT default CI: it skips cleanly without a configured LOCAL endpoint. When the env IS set
|
||||||
|
(and an OpenAI-compatible server such as Ollama is running on loopback), it proves what
|
||||||
|
FakeChatClient cannot — a REAL OpenAIChatCompletionClient non-streaming call returns a
|
||||||
|
response with a load-bearing ``total_token_count > 0`` — and asserts the endpoint is loopback
|
||||||
|
(no-egress: the client only ever talks to the configured ``base_url``, never api.openai.com).
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from agent_framework import Message
|
||||||
|
|
||||||
|
from portfolio_optimiser.backends import LocalBackend
|
||||||
|
|
||||||
|
_BASE_URL = os.environ.get("PORTFOLIO_LOCAL_BASE_URL")
|
||||||
|
_MODEL = os.environ.get("PORTFOLIO_LOCAL_MODEL")
|
||||||
|
_NO_LOCAL = not (_BASE_URL and _MODEL)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
_NO_LOCAL,
|
||||||
|
reason="LOCAL endpoint not configured (set PORTFOLIO_LOCAL_BASE_URL + PORTFOLIO_LOCAL_MODEL)",
|
||||||
|
)
|
||||||
|
async def test_local_profile_real_usage_and_loopback_only() -> None:
|
||||||
|
# No-egress: the configured live endpoint MUST be loopback (never a remote host).
|
||||||
|
assert _BASE_URL is not None
|
||||||
|
assert "127.0.0.1" in _BASE_URL or "localhost" in _BASE_URL, (
|
||||||
|
"live local endpoint must be loopback (no egress)"
|
||||||
|
)
|
||||||
|
client = LocalBackend().create_chat_client(model=_MODEL) # type: ignore[arg-type]
|
||||||
|
reply = await client.get_response(
|
||||||
|
[Message(role="user", contents=["Reply with the single word OK."])]
|
||||||
|
)
|
||||||
|
assert reply.text # a real response came back
|
||||||
|
usage = reply.usage_details
|
||||||
|
# The criterion FakeChatClient cannot prove: real, positive, load-bearing usage.
|
||||||
|
assert usage is not None and (usage.get("total_token_count") or 0) > 0
|
||||||
Loading…
Add table
Add a link
Reference in a new issue