66import requests
77from importlib .metadata import version , PackageNotFoundError
88from urllib .parse import urlparse
9- from dataclasses import dataclass
9+ from dataclasses import dataclass , field , fields
1010
11- API_KEY = os .getenv ("OPENAI_API_KEY" )
1211ENV_VAR_PREFIX = "ASK2API_"
1312TYPE_HINTS = {
1413 "string" : "string" ,
2827
2928@dataclass
3029class Config :
31- base_url : str = "https://api.openai.com/v1"
32- model : str = "gpt-4.1"
33- temperature : float = 0
30+ api_key : str = field (
31+ default = os .getenv ("OPENAI_API_KEY" ),
32+ metadata = {"help" : "API key (required)" },
33+ )
34+ base_url : str = field (
35+ default = "https://api.openai.com/v1" ,
36+ metadata = {"help" : "Base API URL" },
37+ )
38+ model : str = field (
39+ default = "gpt-4.1" ,
40+ metadata = {"help" : "Model name" },
41+ )
42+ temperature : float = field (
43+ default = 0 ,
44+ metadata = {"help" : "Temperature setting" },
45+ )
3446
3547 def __post_init__ (self ):
48+ if not self .api_key :
49+ raise ValueError ("API key is not set!" )
3650 self .openai_url = f"{ self .base_url } /chat/completions"
3751
3852 @classmethod
39- def from_env (cls , prefix : str = ENV_VAR_PREFIX ):
53+ def get_env_vars_help (cls ):
54+ longest = max (len (f .name ) for f in fields (cls ))
55+
56+ def field_help (f ):
57+ desc = f .metadata ["help" ]
58+ default = getattr (cls , f .name ) if f .name != "api_key" else None
59+ return "\t " .join (
60+ [
61+ f"{ ENV_VAR_PREFIX } { f .name .upper ():<{longest }} " ,
62+ f"{ desc } { f'(default: { default } )' if default is not None else '' } " ,
63+ ]
64+ )
65+
66+ return "Environment Variables:\n " + "\n " .join (
67+ field_help (f ) for f in fields (cls )
68+ )
69+
70+ @classmethod
71+ def from_env (cls ):
4072 """Get the configuration from the environment variables."""
4173 return cls (
4274 ** dict (
4375 filter (
4476 lambda x : x [1 ] is not None ,
45- dict (
46- base_url = os .getenv (f"{ prefix } BASE_URL" ),
47- model = os .getenv (f"{ prefix } MODEL" ),
48- temperature = os .getenv (f"{ prefix } TEMPERATURE" ),
49- ).items (),
77+ {
78+ name : os .getenv (ENV_VAR_PREFIX + name .upper ())
79+ for name in cls .__annotations__
80+ }.items (),
5081 ),
5182 )
5283 )
@@ -137,9 +168,9 @@ def convert_example_to_schema(example, _cache=None):
137168 elif isinstance (value , list ):
138169 schema ["properties" ][key ] = {
139170 "type" : "array" ,
140- "items" : convert_example_to_schema ( value [ 0 ], _cache )
141- if value
142- else {} ,
171+ "items" : (
172+ convert_example_to_schema ( value [ 0 ], _cache ) if value else {}
173+ ) ,
143174 }
144175 elif isinstance (value , dict ):
145176 schema ["properties" ][key ] = convert_example_to_schema (value , _cache )
@@ -166,16 +197,9 @@ def convert_example_to_schema(example, _cache=None):
166197
167198
168199def main ():
169- env_vars_help = """
170- Environment Variables:
171- OPENAI_API_KEY OpenAI API key (required)
172- ASK2API_BASE_URL Base API URL (default: https://api.openai.com/v1)
173- ASK2API_MODEL Model name (default: gpt-4.1)
174- ASK2API_TEMPERATURE Temperature setting (default: 0)
175- """
176200 parser = argparse .ArgumentParser (
177201 formatter_class = argparse .RawDescriptionHelpFormatter ,
178- epilog = env_vars_help ,
202+ epilog = Config . get_env_vars_help () ,
179203 )
180204 parser .add_argument (
181205 "-p" ,
@@ -251,7 +275,7 @@ def main():
251275 }
252276
253277 headers = {
254- "Authorization" : f"Bearer { API_KEY } " ,
278+ "Authorization" : f"Bearer { config . api_key } " ,
255279 "Content-Type" : "application/json" ,
256280 }
257281
0 commit comments