Skip to content

Commit 082315c

Browse files
committed
promptify v3.0
1 parent 2ca4c92 commit 082315c

File tree

152 files changed

+3045
-5727
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

152 files changed

+3045
-5727
lines changed

.DS_Store

6 KB
Binary file not shown.

.bumpversion.cfg

Lines changed: 0 additions & 5 deletions
This file was deleted.

README.md

Lines changed: 113 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<h2 align="center">Promptify</h2> -->
66

77
<p align="center">
8-
<p align="center">Prompt Engineering, Solve NLP Problems with LLM's & Easily generate different NLP Task prompts for popular generative models like GPT, PaLM, and more with Promptify
8+
<p align="center">Task-based NLP engine with Pydantic structured outputs, built-in evaluation, and LiteLLM as the universal LLM backend. Think "scikit-learn for LLM-powered NLP".
99
</p>
1010
</p>
1111

@@ -33,104 +33,149 @@
3333

3434
### With pip
3535

36-
This repository is tested on Python 3.7+, openai 0.25+.
37-
38-
You should install Promptify using Pip command
36+
Requires Python 3.9+.
3937

4038
```bash
41-
pip3 install promptify
39+
pip install promptify
4240
```
4341

4442
or
4543

4644
```bash
47-
pip3 install git+https://github.com/promptslab/Promptify.git
45+
pip install git+https://github.com/promptslab/Promptify.git
46+
```
47+
48+
For evaluation metrics support:
49+
```bash
50+
pip install promptify[eval]
4851
```
4952

50-
## Quick tour
53+
## Quick Tour
5154

52-
To immediately use a LLM model for your NLP task, we provide the `Pipeline` API.
55+
### 3-Line NER
5356

5457
```python
55-
from promptify import Prompter,OpenAI, Pipeline
58+
from promptify import NER
5659

57-
sentence = """The patient is a 93-year-old female with a medical
58-
history of chronic right hip pain, osteoporosis,
59-
hypertension, depression, and chronic atrial
60-
fibrillation admitted for evaluation and management
61-
of severe nausea and vomiting and urinary tract
62-
infection"""
60+
ner = NER(model="gpt-4o-mini", domain="medical")
61+
result = ner("The patient is a 93-year-old female with a medical history of chronic right hip pain, osteoporosis, hypertension, depression, and chronic atrial fibrillation admitted for evaluation and management of severe nausea and vomiting and urinary tract infection")
62+
```
6363

64-
model = OpenAI(api_key) # or `HubModel()` for Huggingface-based inference or 'Azure' etc
65-
prompter = Prompter('ner.jinja') # select a template or provide custom template
66-
pipe = Pipeline(prompter , model)
64+
**Output:**
65+
```python
66+
NERResult(entities=[
67+
Entity(text="93-year-old", label="AGE"),
68+
Entity(text="chronic right hip pain", label="CONDITION"),
69+
Entity(text="osteoporosis", label="CONDITION"),
70+
Entity(text="hypertension", label="CONDITION"),
71+
Entity(text="depression", label="CONDITION"),
72+
Entity(text="chronic atrial fibrillation", label="CONDITION"),
73+
Entity(text="severe nausea and vomiting", label="SYMPTOM"),
74+
Entity(text="urinary tract infection", label="CONDITION"),
75+
])
76+
```
6777

78+
### Classification
6879

69-
result = pipe.fit(sentence, domain="medical", labels=None)
80+
```python
81+
from promptify import Classify
82+
83+
clf = Classify(model="gpt-4o-mini", labels=["positive", "negative", "neutral"])
84+
result = clf("Amazing product! Best purchase I've ever made.")
85+
# Classification(label="positive", confidence=0.95)
86+
```
7087

88+
### Question Answering
7189

72-
### Output
90+
```python
91+
from promptify import QA
7392

74-
[
75-
{"E": "93-year-old", "T": "Age"},
76-
{"E": "chronic right hip pain", "T": "Medical Condition"},
77-
{"E": "osteoporosis", "T": "Medical Condition"},
78-
{"E": "hypertension", "T": "Medical Condition"},
79-
{"E": "depression", "T": "Medical Condition"},
80-
{"E": "chronic atrial fibrillation", "T": "Medical Condition"},
81-
{"E": "severe nausea and vomiting", "T": "Symptom"},
82-
{"E": "urinary tract infection", "T": "Medical Condition"},
83-
{"Branch": "Internal Medicine", "Group": "Geriatrics"},
84-
]
85-
93+
qa = QA(model="gpt-4o-mini")
94+
answer = qa("Einstein was born in Ulm in 1879.", question="Where was Einstein born?")
95+
# Answer(answer="Ulm", evidence="Einstein was born in Ulm", confidence=0.98)
8696
```
8797

88-
<p float="left">
89-
<img src="https://raw.githubusercontent.com/promptslab/Promptify/main/assets/ner.png" width="250" />
90-
<img src="https://raw.githubusercontent.com/promptslab/Promptify/main/assets/multilabel.png" width="250" />
91-
<img src="https://raw.githubusercontent.com/promptslab/Promptify/main/assets/qa_gen.png" width="250" />
92-
</p>
93-
<h4 align="center">GPT-3 Example with NER, MultiLabel, Question Generation Task</h3>
98+
### Custom Task with Any Pydantic Schema
99+
100+
```python
101+
from promptify import Task
102+
from pydantic import BaseModel
94103

104+
class MovieReview(BaseModel):
105+
sentiment: str
106+
rating: float
107+
key_themes: list[str]
95108

96-
<h2>Features 🎮 </h2>
97-
<ul>
98-
<li> Perform NLP tasks (such as NER and classification) in just 2 lines of code, with no training data required</li>
99-
<li> Easily add one shot, two shot, or few shot examples to the prompt</li>
100-
<li> Handling out-of-bounds prediction from LLMS (GPT, t5, etc.)</li>
101-
<li> Output always provided as a Python object (e.g. list, dictionary) for easy parsing and filtering. This is a major advantage over LLMs generated output, whose unstructured and raw output makes it difficult to use in business or other applications.</li>
102-
<li> Custom examples and samples can be easily added to the prompt</li>
103-
<li> 🤗 Run inference on any model stored on the Huggingface Hub (see <a href="https://github.com/promptslab/Promptify/blob/main/notebooks/huggingface.ipynb">notebook guide</a>).</li>
104-
<li> Optimized prompts to reduce OpenAI token costs (coming soon)</li>
105-
</ul>
109+
task = Task(model="gpt-4o", output_schema=MovieReview, instruction="Analyze this movie review.")
110+
review = task("Nolan's best work. Stunning visuals but the plot drags.")
111+
# MovieReview(sentiment="mostly positive", rating=7.5, key_themes=["visuals", "pacing"])
112+
```
106113

114+
### Any Provider - Just Change the Model String
107115

108-
### Supporting wide-range of Prompt-Based NLP tasks :
116+
```python
117+
ner_openai = NER(model="gpt-4o-mini")
118+
ner_claude = NER(model="claude-sonnet-4-20250514")
119+
ner_local = NER(model="ollama/llama3")
120+
```
109121

110-
| Task Name | Colab Notebook | Status |
111-
|-------------|-------|-------|
112-
| Named Entity Recognition | [NER Examples with GPT-3](https://colab.research.google.com/drive/16DUUV72oQPxaZdGMH9xH1WbHYu6Jqk9Q?usp=sharing) ||
113-
| Multi-Label Text Classification | [Classification Examples with GPT-3](https://colab.research.google.com/drive/1gNqDxNyMMUO67DxigzRAOa7C_Tcr2g6M?usp=sharing) ||
114-
| Multi-Class Text Classification | [Classification Examples with GPT-3](https://colab.research.google.com/drive/1gNqDxNyMMUO67DxigzRAOa7C_Tcr2g6M?usp=sharing) ||
115-
| Binary Text Classification | [Classification Examples with GPT-3](https://colab.research.google.com/drive/1gNqDxNyMMUO67DxigzRAOa7C_Tcr2g6M?usp=sharing) ||
116-
| Question-Answering | [QA Task Examples with GPT-3](https://colab.research.google.com/drive/1Yhl7iFb7JF0x89r1L3aDuufydVWX_VrL?usp=sharing) ||
117-
| Question-Answer Generation | [QA Task Examples with GPT-3](https://colab.research.google.com/drive/1Yhl7iFb7JF0x89r1L3aDuufydVWX_VrL?usp=sharing) ||
118-
| Relation-Extraction | [Relation-Extraction Examples with GPT-3](https://colab.research.google.com/drive/1iW4QNjllc8ktaQBWh3_04340V-tap1co?usp=sharing) ||
119-
| Summarization | [Summarization Task Examples with GPT-3](https://colab.research.google.com/drive/1PlXIAMDtrK-RyVdDhiSZy6ztcDWsNPNw?usp=sharing) ||
120-
| Explanation | [Explanation Task Examples with GPT-3](https://colab.research.google.com/drive/1PlXIAMDtrK-RyVdDhiSZy6ztcDWsNPNw?usp=sharing) ||
121-
| SQL Writer | [SQL Writer Example with GPT-3](https://colab.research.google.com/drive/1JNUYCTdqkdeIAxiX-NzR-4dngdmWj0rV?usp=sharing) ||
122-
| Tabular Data | | |
123-
| Image Data | | |
124-
| More Prompts | | |
122+
### Batch Processing
125123

124+
```python
125+
results = ner.batch(["text1", "text2", "text3"], max_concurrent=10)
126+
```
126127

127-
## Docs
128+
### Async Support
128129

129-
[Promptify Docs](https://promptify.readthedocs.io/)
130+
```python
131+
result = await ner.acall("Patient has diabetes")
132+
```
133+
134+
### Built-in Evaluation
135+
136+
```python
137+
from promptify.eval import evaluate
138+
139+
scores = evaluate(task=ner, dataset=labeled_data, metrics=["precision", "recall", "f1"])
140+
# {"precision": 0.92, "recall": 0.88, "f1": 0.90}
141+
```
130142

131-
## Community
143+
## Features
144+
145+
- **2-3 lines of code** for any NLP task -no training data required
146+
- **Pydantic structured outputs** -type-safe results, not raw strings
147+
- **Any LLM provider** via LiteLLM -OpenAI, Anthropic, Google, Ollama, Azure, and 100+ more
148+
- **Built-in tasks** -NER, Classification (binary/multiclass/multilabel), QA, Summarization, Relation Extraction, SQL Generation, and more
149+
- **Custom tasks** -bring your own Pydantic schema for any structured output
150+
- **Few-shot examples** -easily add examples to improve accuracy
151+
- **Domain specialization** -pass `domain="medical"` or any domain for context-aware prompts
152+
- **Batch processing** -async concurrency under the hood for processing multiple texts
153+
- **Async support** -native `await` support with `acall()`
154+
- **Evaluation framework** -precision, recall, F1, accuracy, exact match, ROUGE metrics
155+
- **Safe parser** -fallback JSON completion for providers without native structured outputs (no `eval()`)
156+
- **Cost tracking** -built-in token usage and cost monitoring via `get_cost_summary()`
157+
158+
### Supported NLP Tasks
159+
160+
| Task | Class | Output Schema |
161+
|------|-------|---------------|
162+
| Named Entity Recognition | `NER` | `NERResult` (list of `Entity`) |
163+
| Binary Classification | `Classify` | `Classification` |
164+
| Multiclass Classification | `Classify` | `Classification` |
165+
| Multilabel Classification | `Classify(multi_label=True)` | `MultiLabelResult` |
166+
| Question Answering | `QA` | `Answer` |
167+
| Summarization | `Summarize` | `Summary` |
168+
| Relation Extraction | `ExtractRelations` | `ExtractionResult` |
169+
| Tabular Extraction | `ExtractTable` | `ExtractionResult` |
170+
| Question Generation | `GenerateQuestions` | list of `GeneratedQuestion` |
171+
| SQL Generation | `GenerateSQL` | `SQLQuery` |
172+
| Text Normalization | `NormalizeText` | normalized text |
173+
| Topic Modelling | `ExtractTopics` | list of topics |
174+
| Custom Task | `Task` | any Pydantic `BaseModel` |
175+
176+
## Community
132177
<div align="center">
133-
If you are interested in Prompt-Engineering, LLMs, ChatGPT and other latest research discussions, please consider joining <a href="https://discord.gg/m88xfYMbK6">PromptsLab</a></div>
178+
If you are interested in Prompt-Engineering, LLMs, and NLP, please consider joining <a href="https://discord.gg/m88xfYMbK6">PromptsLab</a></div>
134179
<div align="center">
135180
<img alt="Join us on Discord" src="https://img.shields.io/discord/1069129502472556587?color=5865F2&logo=discord&logoColor=white">
136181
</div>

promptify/VERSION

Lines changed: 0 additions & 1 deletion
This file was deleted.

promptify/__init__.py

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,37 @@
1-
__version__ = "2.0.3"
2-
from .parser.parser import Parser
3-
from .prompter.nlp_prompter import Prompter
4-
from .prompter.prompt_cache import PromptCache
5-
from .prompter.template_loader import TemplateLoader
6-
from .prompter.conversation_logger import ConversationLogger
7-
from .models.text2text.api.openai_models import OpenAI
8-
from .models.text2text.api.anthropic import AnthropicModel
9-
from .models.text2text.api.cohere import CohereModel
10-
from .models.text2text.api.azure_openai import Azure
11-
from .models.text2text.api.hub_model import HubModel
12-
from .models.text2text.api.mock_model import MockModel
13-
from .models.text2text.api.base_model import Model
14-
from .utils.file_utils import *
15-
from .utils.data_utils import *
16-
from .utils.conversation_utils import *
17-
from .pipelines import Pipeline
1+
"""Promptify v3 — Task-based NLP engine with structured outputs."""
2+
3+
from promptify._version import __version__
4+
from promptify.core.config import ModelConfig
5+
from promptify.core.logging import setup_logging
6+
from promptify.engine.cost import get_cost_summary
7+
from promptify.tasks import (
8+
NER,
9+
QA,
10+
Classify,
11+
ExtractRelations,
12+
ExtractTable,
13+
ExtractTopics,
14+
GenerateQuestions,
15+
GenerateSQL,
16+
NormalizeText,
17+
Summarize,
18+
Task,
19+
)
20+
21+
__all__ = [
22+
"__version__",
23+
"NER",
24+
"Classify",
25+
"QA",
26+
"Summarize",
27+
"Task",
28+
"ExtractRelations",
29+
"ExtractTable",
30+
"GenerateQuestions",
31+
"GenerateSQL",
32+
"NormalizeText",
33+
"ExtractTopics",
34+
"ModelConfig",
35+
"setup_logging",
36+
"get_cost_summary",
37+
]

promptify/_version.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__version__ = "3.0.0"

promptify/core/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from promptify.core.config import ModelConfig, CacheConfig
2+
from promptify.core.exceptions import PromptifyError
3+
from promptify.core.logging import setup_logging
4+
5+
__all__ = ["ModelConfig", "CacheConfig", "PromptifyError", "setup_logging"]

promptify/core/config.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
"""Pydantic configuration models."""
2+
3+
from __future__ import annotations
4+
5+
from typing import Any, Dict, List, Literal, Optional, Union
6+
7+
from pydantic import BaseModel, Field, field_validator
8+
9+
10+
class ModelConfig(BaseModel):
11+
"""Configuration for the LLM engine."""
12+
13+
model: str = Field(description="Model identifier (e.g. 'gpt-4o-mini', 'claude-sonnet-4-20250514')")
14+
api_key: Optional[str] = Field(default=None, description="API key (falls back to env var)")
15+
temperature: float = Field(default=0.0, ge=0.0, le=2.0)
16+
top_p: float = Field(default=1.0, ge=0.0, le=1.0)
17+
max_tokens: Optional[int] = Field(default=None, gt=0)
18+
stop: Optional[Union[str, List[str]]] = None
19+
presence_penalty: float = Field(default=0.0, ge=-2.0, le=2.0)
20+
frequency_penalty: float = Field(default=0.0, ge=-2.0, le=2.0)
21+
timeout: Optional[float] = Field(default=None, gt=0)
22+
max_retries: int = Field(default=3, ge=0, le=20)
23+
extra_params: Dict[str, Any] = Field(default_factory=dict)
24+
25+
model_config = {"frozen": False}
26+
27+
28+
class CacheConfig(BaseModel):
29+
"""Configuration for response caching."""
30+
31+
enabled: bool = True
32+
backend: Literal["memory", "disk", "redis"] = "memory"
33+
maxsize: int = Field(default=128, gt=0)
34+
ttl: Optional[int] = Field(default=3600, gt=0, description="TTL in seconds")
35+
redis_url: Optional[str] = None
36+
37+
@field_validator("redis_url")
38+
@classmethod
39+
def validate_redis_url(cls, v: Optional[str], info: Any) -> Optional[str]:
40+
if info.data.get("backend") == "redis" and not v:
41+
raise ValueError("redis_url is required when backend is 'redis'")
42+
return v

promptify/core/exceptions.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
"""Promptify exception hierarchy."""
2+
3+
4+
class PromptifyError(Exception):
5+
"""Base exception for all Promptify errors."""
6+
7+
8+
class ConfigurationError(PromptifyError):
9+
"""Invalid configuration."""
10+
11+
12+
class ModelError(PromptifyError):
13+
"""Base for model-related errors."""
14+
15+
16+
class ModelConnectionError(ModelError):
17+
"""Failed to connect to model provider."""
18+
19+
20+
class ModelAuthenticationError(ModelError):
21+
"""Invalid API key or authentication failure."""
22+
23+
24+
class ModelRateLimitError(ModelError):
25+
"""Rate limit exceeded."""
26+
27+
28+
class ModelResponseError(ModelError):
29+
"""Invalid or unexpected model response."""
30+
31+
32+
class TemplateError(PromptifyError):
33+
"""Base for template-related errors."""
34+
35+
36+
class TemplateNotFoundError(TemplateError):
37+
"""Template file not found."""
38+
39+
40+
class TemplateMissingVariableError(TemplateError):
41+
"""Required template variable not provided."""
42+
43+
44+
class ParserError(PromptifyError):
45+
"""Failed to parse model output."""
46+
47+
48+
class PipelineError(PromptifyError):
49+
"""Error in task pipeline execution."""
50+
51+
52+
class EvaluationError(PromptifyError):
53+
"""Error during evaluation."""

0 commit comments

Comments
 (0)