Skip to content

Commit 744c042

Browse files
committed
refactor(Config): enhance configuration management and environment variable handling
- Updated the `Config` dataclass to include metadata for each field, improving documentation and usability. - Implemented a method to generate help text for environment variables dynamically. - Modified the main function to utilize the new `get_env_vars_help` method for clearer CLI output. - Updated README to reflect changes in API key environment variable naming and added details for usage.
1 parent 68662f0 commit 744c042

File tree

2 files changed

+56
-26
lines changed

2 files changed

+56
-26
lines changed

README.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@ Key features:
3030
pip install ask2api
3131
```
3232

33-
Set your OpenAI key:
33+
Set your API key:
3434

3535
```bash
36-
export OPENAI_API_KEY="your_api_key"
36+
export ASK2API_API_KEY="your_api_key"
37+
# Or you can pass OpenAI key
38+
# export OPENAI_API_KEY="your_api_key"
3739
```
3840

3941
## Usage
@@ -65,7 +67,9 @@ And get a structured API response:
6567
}
6668
```
6769

68-
For more complex structures with different data types:
70+
<details>
71+
72+
<summary>For more complex structures with different data types:</summary>
6973

7074
```bash
7175
ask2api -p "Analyze carbon element" -e '{
@@ -103,6 +107,8 @@ Output:
103107
}
104108
```
105109

110+
</details>
111+
106112
### Vision modality
107113

108114
You can also analyze images and get structured JSON responses:

ask2api.py

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@
66
import requests
77
from importlib.metadata import version, PackageNotFoundError
88
from 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")
1211
ENV_VAR_PREFIX = "ASK2API_"
1312
TYPE_HINTS = {
1413
"string": "string",
@@ -28,25 +27,57 @@
2827

2928
@dataclass
3029
class 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

168199
def 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

Comments
 (0)