prompture 0.0.25.dev2__tar.gz → 0.0.26.dev2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/.env.copy +26 -1
  2. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/.github/scripts/update_wrapper_version.py +6 -2
  3. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/.github/workflows/publish.yml +3 -4
  4. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/PKG-INFO +33 -24
  5. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/README.md +31 -24
  6. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/prompture/core.py +187 -74
  7. prompture-0.0.26.dev2/prompture/drivers/__init__.py +120 -0
  8. prompture-0.0.26.dev2/prompture/drivers/google_driver.py +127 -0
  9. prompture-0.0.26.dev2/prompture/drivers/grok_driver.py +153 -0
  10. prompture-0.0.26.dev2/prompture/drivers/groq_driver.py +117 -0
  11. prompture-0.0.26.dev2/prompture/drivers/lmstudio_driver.py +93 -0
  12. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/prompture/drivers/ollama_driver.py +1 -1
  13. prompture-0.0.26.dev2/prompture/drivers/openrouter_driver.py +140 -0
  14. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/prompture/settings.py +34 -1
  15. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/prompture.egg-info/PKG-INFO +33 -24
  16. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/prompture.egg-info/SOURCES.txt +6 -1
  17. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/prompture.egg-info/requires.txt +2 -0
  18. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/setup.py +2 -0
  19. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/test.py +20 -22
  20. prompture-0.0.25.dev2/prompture/drivers/__init__.py +0 -45
  21. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/.github/FUNDING.yml +0 -0
  22. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/.github/workflows/dev.yml +0 -0
  23. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/LICENSE +0 -0
  24. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/MANIFEST.in +0 -0
  25. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/VERSION +0 -0
  26. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/packages/README.md +0 -0
  27. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/packages/llm_to_json/__init__.py +0 -0
  28. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/packages/pyproject.toml +0 -0
  29. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/packages/test.py +0 -0
  30. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/prompture/__init__.py +0 -0
  31. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/prompture/cli.py +0 -0
  32. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/prompture/driver.py +0 -0
  33. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/prompture/drivers/azure_driver.py +0 -0
  34. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/prompture/drivers/claude_driver.py +0 -0
  35. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/prompture/drivers/hugging_driver.py +0 -0
  36. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/prompture/drivers/local_http_driver.py +0 -0
  37. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/prompture/drivers/openai_driver.py +0 -0
  38. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/prompture/runner.py +0 -0
  39. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/prompture/tools.py +0 -0
  40. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/prompture/validator.py +0 -0
  41. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/prompture.egg-info/dependency_links.txt +0 -0
  42. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/prompture.egg-info/entry_points.txt +0 -0
  43. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/prompture.egg-info/top_level.txt +0 -0
  44. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/requirements.txt +0 -0
  45. {prompture-0.0.25.dev2 → prompture-0.0.26.dev2}/setup.cfg +0 -0
@@ -19,6 +19,11 @@ CLAUDE_MODEL=claude-3-sonnet-20240229
19
19
  OLLAMA_URI=http://localhost:11434
20
20
  OLLAMA_MODEL=gemma:latest
21
21
 
22
+ # LM Studio Configuration
23
+ # Required if AI_PROVIDER=lmstudio
24
+ LMSTUDIO_ENDPOINT=http://127.0.0.1:1234/v1/chat/completions
25
+ LMSTUDIO_MODEL=deepseek/deepseek-r1-0528-qwen3-8b
26
+
22
27
  # Azure OpenAI Configuration
23
28
  AZURE_API_KEY=
24
29
  AZURE_API_ENDPOINT=
@@ -32,4 +37,24 @@ HF_TOKEN=
32
37
 
33
38
  # Local HTTP Configuration
34
39
  LOCAL_HTTP_ENDPOINT=http://localhost:8000/generate
35
- LOCAL_HTTP_MODEL=local-model
40
+ LOCAL_HTTP_MODEL=local-model
41
+
42
+ # Google Configuration
43
+ # Required if AI_PROVIDER=google
44
+ GOOGLE_API_KEY=your-api-key-here
45
+ GOOGLE_MODEL=gemini-1.5-pro
46
+
47
+ # Groq Configuration
48
+ # Required if AI_PROVIDER=groq
49
+ GROQ_API_KEY=your-api-key-here
50
+ GROQ_MODEL=llama2-70b-4096
51
+
52
+ # OpenRouter Configuration
53
+ # Required if AI_PROVIDER=openrouter
54
+ OPENROUTER_API_KEY=your-api-key-here
55
+ OPENROUTER_MODEL=openai/gpt-3.5-turbo
56
+
57
+ # Grok Configuration
58
+ # Required if AI_PROVIDER=grok
59
+ GROK_API_KEY=your-api-key-here
60
+ GROK_MODEL=grok-4-fast-reasoning
@@ -15,8 +15,12 @@ def main():
15
15
  # Update version
16
16
  data["project"]["version"] = new_version
17
17
 
18
- # Optionally update dependencies here if needed
19
- # Example: data["project"]["dependencies"] = ["prompture>=" + new_version]
18
+ # Update prompture dependency
19
+ if "dependencies" in data["project"]:
20
+ for i, dep in enumerate(data["project"]["dependencies"]):
21
+ if dep.startswith("prompture"):
22
+ data["project"]["dependencies"][i] = f"prompture>={new_version}"
23
+ break
20
24
 
21
25
  with open(PYPROJECT_PATH, "w", encoding="utf-8") as f:
22
26
  toml.dump(data, f)
@@ -91,10 +91,8 @@ jobs:
91
91
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
92
92
  with:
93
93
  tag_name: v${{ steps.bump_version.outputs.new_version }}
94
- release_name: Release v${{ steps.bump_version.outputs.new_version }}
95
- body: |
96
- # ${{ steps.fetch_pr.outputs.result != 'null' && fromJSON(steps.fetch_pr.outputs.result).title || 'New Release' }}
97
-
94
+ release_name: v${{ steps.bump_version.outputs.new_version }}
95
+ body: |
98
96
  ## Changes
99
97
  ${{ steps.fetch_pr.outputs.result != 'null' && fromJSON(steps.fetch_pr.outputs.result).body || 'Version update' }}
100
98
 
@@ -148,6 +146,7 @@ jobs:
148
146
  run: |
149
147
  NEW_VERSION=${{ steps.bump_version.outputs.new_version }}
150
148
  echo "Pinning wrapper to version $NEW_VERSION"
149
+ pip install toml
151
150
  python .github/scripts/update_wrapper_version.py "$NEW_VERSION"
152
151
 
153
152
  # Build wrapper package --------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: prompture
3
- Version: 0.0.25.dev2
3
+ Version: 0.0.26.dev2
4
4
  Summary: Ask LLMs to return structured JSON and run cross-model tests. API-first.
5
5
  Home-page: https://github.com/jhd3197/prompture
6
6
  Author: Juan Denis
@@ -13,6 +13,8 @@ Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
14
  Requires-Dist: anthropic>=0.8.0
15
15
  Requires-Dist: click>=8.0
16
+ Requires-Dist: google-generativeai>=0.3.0
17
+ Requires-Dist: groq>=0.4.0
16
18
  Requires-Dist: httpx>=0.25.0
17
19
  Requires-Dist: jsonschema>=4.0
18
20
  Requires-Dist: openai>=1.0.0
@@ -44,7 +46,7 @@ Dynamic: summary
44
46
 
45
47
  - ✅ **Structured output** → JSON schema enforcement, or direct **Pydantic** instances
46
48
  - ✅ **Stepwise extraction** → Per-field prompts, with smart type conversion (incl. shorthand numbers)
47
- - ✅ **Multi-driver** → OpenAI, Azure, Claude, Ollama, HTTP, Mock, HuggingFace (via `get_driver()`)
49
+ - ✅ **Multi-driver** → OpenAI, Azure, Claude, Ollama, LM Studio, Google, Groq, OpenRouter, Grok, HTTP, Mock, HuggingFace (via `get_driver()`)
48
50
  - ✅ **Usage & cost** → Token + $ tracking on every call (`usage` from driver meta)
49
51
  - ✅ **AI cleanup** → Optional LLM pass to fix malformed JSON
50
52
  - ✅ **Batch testing** → Define suites and compare models (spec-driven)
@@ -72,27 +74,39 @@ pip install prompture
72
74
 
73
75
  ## Configure a Provider
74
76
 
75
- `get_driver()` (used by high-level helpers) selects a driver from env:
77
+ Model names now support provider prefixes (e.g., "ollama/llama3.1:8b"). The `get_driver_for_model()` function automatically selects the appropriate driver based on the provider prefix.
78
+
79
+ You can configure providers either through environment variables or by using provider-prefixed model names:
76
80
 
77
81
  ```bash
78
- # One of: ollama | openai | azure | claude | http | huggingface
79
- export AI_PROVIDER=ollama
82
+ # Environment variable approach:
83
+ export AI_PROVIDER=ollama # One of: ollama | openai | azure | claude | google | groq | openrouter | grok | lmstudio | http | huggingface
80
84
 
81
85
  # Only if the provider needs them:
82
86
  export OPENAI_API_KEY=...
83
87
  export AZURE_OPENAI_ENDPOINT=...
84
88
  export AZURE_OPENAI_API_KEY=...
85
89
  export ANTHROPIC_API_KEY=...
90
+ export GOOGLE_API_KEY=...
91
+ export GROQ_API_KEY=...
92
+ export OPENROUTER_API_KEY=...
93
+ export GROK_API_KEY=...
94
+ export LMSTUDIO_ENDPOINT=...
86
95
  ```
87
96
 
88
- | Provider (AI_PROVIDER) | Example models | Cost calc |
89
- | ---------------------- | --------------------------- | --------------- |
90
- | `ollama` | `llama3.1:8b`, `qwen2.5:3b` | `$0.00` (local) |
91
- | `openai` | `gpt-*` | Automatic |
92
- | `azure` | Deployed names | Automatic |
93
- | `claude` | `claude-*` | Automatic |
94
- | `huggingface` | local/endpoint | `$0.00` (local) |
95
- | `http` | self-hosted | `$0.00` |
97
+ | Provider | Example models | Cost calc |
98
+ | -------- | ------------------------------------- | --------------- |
99
+ | `ollama` | `ollama/llama3.1:8b`, `ollama/qwen2.5:3b` | `$0.00` (local) |
100
+ | `openai` | `openai/gpt-4`, `openai/gpt-3.5-turbo` | Automatic |
101
+ | `azure` | `azure/deployed-name` | Automatic |
102
+ | `claude` | `claude/claude-3` | Automatic |
103
+ | `google` | `google/gemini-1.5-pro`, `google/gemini-1.5-flash` | Automatic |
104
+ | `groq` | `groq/llama2-70b-4096`, `groq/mixtral-8x7b-32768` | Automatic |
105
+ | `openrouter` | `openrouter/openai/gpt-3.5-turbo`, `openrouter/anthropic/claude-2` | Automatic |
106
+ | `grok` | `grok/grok-4-fast-reasoning`, `grok/grok-3-mini` | Automatic |
107
+ | `lmstudio` | `lmstudio/local-model` | `$0.00` (local) |
108
+ | `huggingface` | `hf/local-or-endpoint` | `$0.00` (local) |
109
+ | `http` | `http/self-hosted` | `$0.00` |
96
110
 
97
111
  ---
98
112
 
@@ -115,8 +129,8 @@ class Person(BaseModel):
115
129
 
116
130
  text = "Maria is 32, a software developer in New York. She loves hiking and photography."
117
131
 
118
- # Uses get_driver() internally (AI_PROVIDER). You can still pass driver/model_name.
119
- person = extract_with_model(Person, text, model_name="gpt-oss:20b")
132
+ # Uses get_driver_for_model() internally based on model name prefix
133
+ person = extract_with_model(Person, text, model_name="ollama/gpt-oss:20b")
120
134
  print(person.dict())
121
135
  ```
122
136
 
@@ -127,14 +141,11 @@ print(person.dict())
127
141
  ## JSON-first (low-level primitives)
128
142
 
129
143
  When you want raw JSON with a schema and full control, use `ask_for_json` or `extract_and_jsonify`.
130
- **Note:** these require an explicit `driver`.
131
144
 
132
145
  ```python
133
146
  from prompture.drivers import get_driver
134
147
  from prompture import ask_for_json, extract_and_jsonify
135
148
 
136
- driver = get_driver("ollama") # or "openai", "azure", etc.
137
-
138
149
  schema = {
139
150
  "type": "object",
140
151
  "required": ["name", "age"],
@@ -146,19 +157,17 @@ schema = {
146
157
 
147
158
  # 1) ask_for_json: you provide the full content prompt
148
159
  resp1 = ask_for_json(
149
- driver=driver,
150
160
  content_prompt="Extract the person's info from: John is 28 and lives in Miami.",
151
161
  json_schema=schema,
152
- options={"model": "llama3.1:8b"}
162
+ model_name="google/gemini-1.5-pro"
153
163
  )
154
164
  print(resp1["json_object"], resp1["usage"])
155
165
 
156
166
  # 2) extract_and_jsonify: you provide text & an instruction template; it builds the prompt
157
167
  resp2 = extract_and_jsonify(
158
- driver=driver,
159
168
  text="John is 28 and lives in Miami.",
160
169
  json_schema=schema,
161
- model_name="llama3.1:8b",
170
+ model_name="groq/mixtral-8x7b-32768",
162
171
  instruction_template="Extract the person's information:"
163
172
  )
164
173
  print(resp2["json_object"], resp2["usage"])
@@ -204,10 +213,10 @@ Prompture supports two Pydantic extraction modes:
204
213
  ```python
205
214
  from prompture import extract_with_model, stepwise_extract_with_model
206
215
 
207
- person1 = extract_with_model(Person, text, model_name="gpt-oss:20b")
216
+ person1 = extract_with_model(Person, text, model_name="openrouter/anthropic/claude-2")
208
217
  print(person1.dict())
209
218
 
210
- res = stepwise_extract_with_model(Person, text, model_name="gpt-oss:20b")
219
+ res = stepwise_extract_with_model(Person, text, model_name="grok/grok-4-fast-reasoning")
211
220
  print(res["model"].dict())
212
221
  print(res["usage"]) # includes per-field usage and totals
213
222
  ```
@@ -6,7 +6,7 @@
6
6
 
7
7
  - ✅ **Structured output** → JSON schema enforcement, or direct **Pydantic** instances
8
8
  - ✅ **Stepwise extraction** → Per-field prompts, with smart type conversion (incl. shorthand numbers)
9
- - ✅ **Multi-driver** → OpenAI, Azure, Claude, Ollama, HTTP, Mock, HuggingFace (via `get_driver()`)
9
+ - ✅ **Multi-driver** → OpenAI, Azure, Claude, Ollama, LM Studio, Google, Groq, OpenRouter, Grok, HTTP, Mock, HuggingFace (via `get_driver()`)
10
10
  - ✅ **Usage & cost** → Token + $ tracking on every call (`usage` from driver meta)
11
11
  - ✅ **AI cleanup** → Optional LLM pass to fix malformed JSON
12
12
  - ✅ **Batch testing** → Define suites and compare models (spec-driven)
@@ -34,27 +34,39 @@ pip install prompture
34
34
 
35
35
  ## Configure a Provider
36
36
 
37
- `get_driver()` (used by high-level helpers) selects a driver from env:
37
+ Model names now support provider prefixes (e.g., "ollama/llama3.1:8b"). The `get_driver_for_model()` function automatically selects the appropriate driver based on the provider prefix.
38
+
39
+ You can configure providers either through environment variables or by using provider-prefixed model names:
38
40
 
39
41
  ```bash
40
- # One of: ollama | openai | azure | claude | http | huggingface
41
- export AI_PROVIDER=ollama
42
+ # Environment variable approach:
43
+ export AI_PROVIDER=ollama # One of: ollama | openai | azure | claude | google | groq | openrouter | grok | lmstudio | http | huggingface
42
44
 
43
45
  # Only if the provider needs them:
44
46
  export OPENAI_API_KEY=...
45
47
  export AZURE_OPENAI_ENDPOINT=...
46
48
  export AZURE_OPENAI_API_KEY=...
47
49
  export ANTHROPIC_API_KEY=...
50
+ export GOOGLE_API_KEY=...
51
+ export GROQ_API_KEY=...
52
+ export OPENROUTER_API_KEY=...
53
+ export GROK_API_KEY=...
54
+ export LMSTUDIO_ENDPOINT=...
48
55
  ```
49
56
 
50
- | Provider (AI_PROVIDER) | Example models | Cost calc |
51
- | ---------------------- | --------------------------- | --------------- |
52
- | `ollama` | `llama3.1:8b`, `qwen2.5:3b` | `$0.00` (local) |
53
- | `openai` | `gpt-*` | Automatic |
54
- | `azure` | Deployed names | Automatic |
55
- | `claude` | `claude-*` | Automatic |
56
- | `huggingface` | local/endpoint | `$0.00` (local) |
57
- | `http` | self-hosted | `$0.00` |
57
+ | Provider | Example models | Cost calc |
58
+ | -------- | ------------------------------------- | --------------- |
59
+ | `ollama` | `ollama/llama3.1:8b`, `ollama/qwen2.5:3b` | `$0.00` (local) |
60
+ | `openai` | `openai/gpt-4`, `openai/gpt-3.5-turbo` | Automatic |
61
+ | `azure` | `azure/deployed-name` | Automatic |
62
+ | `claude` | `claude/claude-3` | Automatic |
63
+ | `google` | `google/gemini-1.5-pro`, `google/gemini-1.5-flash` | Automatic |
64
+ | `groq` | `groq/llama2-70b-4096`, `groq/mixtral-8x7b-32768` | Automatic |
65
+ | `openrouter` | `openrouter/openai/gpt-3.5-turbo`, `openrouter/anthropic/claude-2` | Automatic |
66
+ | `grok` | `grok/grok-4-fast-reasoning`, `grok/grok-3-mini` | Automatic |
67
+ | `lmstudio` | `lmstudio/local-model` | `$0.00` (local) |
68
+ | `huggingface` | `hf/local-or-endpoint` | `$0.00` (local) |
69
+ | `http` | `http/self-hosted` | `$0.00` |
58
70
 
59
71
  ---
60
72
 
@@ -77,8 +89,8 @@ class Person(BaseModel):
77
89
 
78
90
  text = "Maria is 32, a software developer in New York. She loves hiking and photography."
79
91
 
80
- # Uses get_driver() internally (AI_PROVIDER). You can still pass driver/model_name.
81
- person = extract_with_model(Person, text, model_name="gpt-oss:20b")
92
+ # Uses get_driver_for_model() internally based on model name prefix
93
+ person = extract_with_model(Person, text, model_name="ollama/gpt-oss:20b")
82
94
  print(person.dict())
83
95
  ```
84
96
 
@@ -89,14 +101,11 @@ print(person.dict())
89
101
  ## JSON-first (low-level primitives)
90
102
 
91
103
  When you want raw JSON with a schema and full control, use `ask_for_json` or `extract_and_jsonify`.
92
- **Note:** these require an explicit `driver`.
93
104
 
94
105
  ```python
95
106
  from prompture.drivers import get_driver
96
107
  from prompture import ask_for_json, extract_and_jsonify
97
108
 
98
- driver = get_driver("ollama") # or "openai", "azure", etc.
99
-
100
109
  schema = {
101
110
  "type": "object",
102
111
  "required": ["name", "age"],
@@ -108,19 +117,17 @@ schema = {
108
117
 
109
118
  # 1) ask_for_json: you provide the full content prompt
110
119
  resp1 = ask_for_json(
111
- driver=driver,
112
120
  content_prompt="Extract the person's info from: John is 28 and lives in Miami.",
113
121
  json_schema=schema,
114
- options={"model": "llama3.1:8b"}
122
+ model_name="google/gemini-1.5-pro"
115
123
  )
116
124
  print(resp1["json_object"], resp1["usage"])
117
125
 
118
126
  # 2) extract_and_jsonify: you provide text & an instruction template; it builds the prompt
119
127
  resp2 = extract_and_jsonify(
120
- driver=driver,
121
128
  text="John is 28 and lives in Miami.",
122
129
  json_schema=schema,
123
- model_name="llama3.1:8b",
130
+ model_name="groq/mixtral-8x7b-32768",
124
131
  instruction_template="Extract the person's information:"
125
132
  )
126
133
  print(resp2["json_object"], resp2["usage"])
@@ -166,10 +173,10 @@ Prompture supports two Pydantic extraction modes:
166
173
  ```python
167
174
  from prompture import extract_with_model, stepwise_extract_with_model
168
175
 
169
- person1 = extract_with_model(Person, text, model_name="gpt-oss:20b")
176
+ person1 = extract_with_model(Person, text, model_name="openrouter/anthropic/claude-2")
170
177
  print(person1.dict())
171
178
 
172
- res = stepwise_extract_with_model(Person, text, model_name="gpt-oss:20b")
179
+ res = stepwise_extract_with_model(Person, text, model_name="grok/grok-4-fast-reasoning")
173
180
  print(res["model"].dict())
174
181
  print(res["usage"]) # includes per-field usage and totals
175
182
  ```
@@ -253,4 +260,4 @@ This example script compares multiple Ollama models on a complex task of extract
253
260
 
254
261
  ## Contributing
255
262
 
256
- PRs welcome! Add tests and—if adding drivers or patterns—drop an example under `examples/`.
263
+ PRs welcome! Add tests and—if adding drivers or patterns—drop an example under `examples/`.