-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsystem_client.py
More file actions
112 lines (82 loc) · 2.81 KB
/
system_client.py
File metadata and controls
112 lines (82 loc) · 2.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
from __future__ import annotations
import os
from typing import Any, Dict, Protocol
from openai import OpenAI
SYSTEM_PROMPT_VERSION = "v1.0-wine-recommendation"
class SystemClientError(RuntimeError):
"""Raised when the system-under-test client fails to produce a valid response."""
class SystemClient(Protocol):
def generate(self, query: str) -> str:
...
def _get_openai_client() -> OpenAI:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise SystemClientError("OPENAI_API_KEY env var not set.")
return OpenAI(api_key=api_key)
def generate_openai_response(
query: str,
model: str = "gpt-4o-mini",
temperature: float = 0.0,
) -> str:
"""
Generate a response from the current system under test using OpenAI.
This remains the generation client, not the evaluation layer.
The current implementation is still wine-specific and OpenAI-backed.
"""
system_prompt = """
You are a helpful wine recommendation assistant.
STRICT RULES:
- Recommend EXACTLY 3 wines
- ALL wines must be RED wines
- ALL wines must be UNDER 50 euros
- Each recommendation must include:
- Wine name
- Region and country
- Approximate price in euros
- Short tasting note
FORMAT:
1. Wine Name — Region, Country — €Price
Tasting note.
2. Wine Name — Region, Country — €Price
Tasting note.
3. Wine Name — Region, Country — €Price
Tasting note.
Do not include anything else.
"""
client = _get_openai_client()
try:
resp = client.chat.completions.create(
model=model,
temperature=temperature,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": query},
],
)
except Exception as exc:
raise SystemClientError(f"OpenAI request failed: {exc}") from exc
try:
content = resp.choices[0].message.content or ""
except Exception as exc:
raise SystemClientError("Malformed response from OpenAI.") from exc
if not content.strip():
raise SystemClientError("OpenAI returned empty response.")
return content
class OpenAISystemClient:
def __init__(self, model: str, temperature: float):
self.model = model
self.temperature = temperature
def generate(self, query: str) -> str:
return generate_openai_response(
query=query,
model=self.model,
temperature=self.temperature,
)
def build_system_client(system_config: Dict[str, Any]) -> SystemClient:
provider = system_config.get("provider")
if provider == "openai":
return OpenAISystemClient(
model=system_config["model"],
temperature=system_config.get("temperature", 0.0),
)
raise ValueError(f"Unsupported system provider: {provider}")