Skip to content

Commit 51064f3

Browse files
committed
Add country types
1 parent 1053e7d commit 51064f3

File tree

6 files changed

+62
-9
lines changed

6 files changed

+62
-9
lines changed

docs/reference/types.md

+19-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,18 @@
22

33
Outlines provides custom Pydantic types so you can focus on your use case rather than on writing regular expressions:
44

5-
- Using `outlines.types.ZipCode` will generate valid US Zip(+4) codes.
6-
- Using `outlines.types.PhoneNumber` will generate valid US phone numbers.
7-
- Using `outlines.types.ISBN` will generate ISBNs. Note that there is no guarantee that the [check digit](https://en.wikipedia.org/wiki/ISBN#Check_digits) will be correct.
8-
- Using `outlines.types.airports.IATA` will generate valid airport IATA codes.
5+
6+
| Category | Type | Import | Description |
7+
|:--------:|:----:|:-------|:------------|
8+
| Zip code | US | `outlines.types.ZipCode` | Generate US Zip(+4) codes |
9+
| Phone number | US | `outlines.types.PhoneNumber` | Generate valid US phone numbers |
10+
| ISBN | 10 & 13 | `outlines.types.ISBN` | There is no guarantee that the [check digit][wiki-isbn] will be correct |
11+
| Airport | IATA | `outlines.types.airports.IATA` | Valid [airport IATA codes][wiki-airport-iata] |
12+
| Country | alpha-2 code | `outlines.types.airports.Alpha2` | Valid [country alpha-2 codes][wiki-country-alpha-2] |
13+
| | alpha-3 code | `outlines.types.countries.Alpha3` | Valid [country alpha-3 codes][wiki-country-alpha-3] |
14+
| | numeric code | `outlines.types.countries.Numeric` | Valid [country numeric codes][wiki-country-numeric] |
15+
| | name | `outlines.types.countries.Name` | Valid country names |
16+
| | flag | `outlines.types.countries.Flag` | Valid flag emojis |
917

1018
You can use these types in Pydantic schemas for JSON-structured generation:
1119

@@ -49,3 +57,10 @@ print(result)
4957

5058

5159
We plan on adding many more custom types. If you have found yourself writing regular expressions to generate fields of a given type, or if you could benefit from more specific types don't hesite to [submit a PR](https://github.com/outlines-dev/outlines/pulls) or [open an issue](https://github.com/outlines-dev/outlines/issues/new/choose).
60+
61+
62+
[wiki-isbn]: https://en.wikipedia.org/wiki/ISBN#Check_digits
63+
[wiki-airport-iata]: https://en.wikipedia.org/wiki/IATA_airport_code
64+
[wiki-country-alpha-2]: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
65+
[wiki-country-alpha-3]: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3
66+
[wiki-country-numeric]: https://en.wikipedia.org/wiki/ISO_3166-1_numeric

outlines/fsm/types.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,12 @@ def custom_format_fn(sequence: str) -> Any:
3232

3333
if isinstance(python_type, EnumMeta):
3434
values = python_type.__members__.keys()
35-
regex_str = "(" + "|".join(values) + ")"
36-
format_fn = lambda x: str(x)
35+
enum_regex_str: str = "(" + "|".join(values) + ")"
3736

38-
return regex_str, format_fn
37+
def enum_format_fn(sequence: str) -> str:
38+
return str(sequence)
39+
40+
return enum_regex_str, enum_format_fn
3941

4042
if python_type == float:
4143

outlines/types/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1+
from . import airports, countries
12
from .isbn import ISBN
23
from .phone_numbers import PhoneNumber
34
from .zip_codes import ZipCode
4-
from . import airports

outlines/types/countries.py

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""Generate valid country codes and names."""
2+
from enum import Enum
3+
4+
try:
5+
import pycountry
6+
except ImportError:
7+
raise ImportError(
8+
'The `countries` module requires "pycountry" to be installed. You can install it with "pip install pycountry"'
9+
)
10+
11+
ALPHA_2_CODE = [(country.alpha_2, country.alpha_2) for country in pycountry.countries]
12+
Alpha2 = Enum("Alpha_2", ALPHA_2_CODE) # type:ignore
13+
14+
ALPHA_3_CODE = [(country.alpha_3, country.alpha_3) for country in pycountry.countries]
15+
Alpha3 = Enum("Alpha_2", ALPHA_3_CODE) # type:ignore
16+
17+
NUMERIC_CODE = [(country.numeric, country.numeric) for country in pycountry.countries]
18+
Numeric = Enum("Numeric_code", NUMERIC_CODE) # type:ignore
19+
20+
NAME = [(country.name, country.name) for country in pycountry.countries]
21+
Name = Enum("Name", NAME) # type:ignore
22+
23+
FLAG = [(country.flag, country.flag) for country in pycountry.countries]
24+
Flag = Enum("Flag", FLAG) # type:ignore

pyproject.toml

+3
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ test = [
5757
"vllm",
5858
"torch",
5959
"transformers",
60+
"pycountry",
61+
"pyairports",
6062
]
6163
serve = [
6264
"vllm>=0.3.0",
@@ -126,6 +128,7 @@ module = [
126128
"vllm.*",
127129
"uvicorn.*",
128130
"fastapi.*",
131+
"pycountry.*",
129132
"pyairports.*",
130133
]
131134
ignore_missing_imports = true

tests/test_types.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,19 @@ class Model(BaseModel):
4747
[
4848
(types.airports.IATA, "CDG", True),
4949
(types.airports.IATA, "XXX", False),
50+
(types.countries.Alpha2, "FR", True),
51+
(types.countries.Alpha2, "XX", False),
52+
(types.countries.Alpha3, "UKR", True),
53+
(types.countries.Alpha3, "XXX", False),
54+
(types.countries.Numeric, "004", True),
55+
(types.countries.Numeric, "900", False),
56+
(types.countries.Name, "Ukraine", True),
57+
(types.countries.Name, "Wonderland", False),
58+
(types.countries.Flag, "🇿🇼", True),
59+
(types.countries.Flag, "🤗", False),
5060
],
5161
)
5262
def test_type_enum(custom_type, test_string, should_match):
53-
5463
type_name = custom_type.__name__
5564

5665
class Model(BaseModel):

0 commit comments

Comments
 (0)