Skip to content

Commit cfce81b

Browse files
committed
Make timeouts configurable in semantic LLM operations
1 parent 8935115 commit cfce81b

File tree

25 files changed

+471
-19
lines changed

25 files changed

+471
-19
lines changed

src/fenic/_backends/local/semantic_operators/analyze_sentiment.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ def __init__(
134134
model: LanguageModel,
135135
temperature: float,
136136
model_alias: Optional[ResolvedModelAlias] = None,
137+
request_timeout: Optional[float] = None,
137138
):
138139
super().__init__(
139140
input,
@@ -145,6 +146,7 @@ def __init__(
145146
temperature=temperature,
146147
response_format=SENTIMENT_ANALYSIS_FORMAT,
147148
model_profile=model_alias.profile if model_alias else None,
149+
request_timeout=request_timeout,
148150
),
149151
),
150152
EXAMPLES,

src/fenic/_backends/local/semantic_operators/base.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ def send_requests(
7878
response_format=self.inference_config.response_format,
7979
top_logprobs=self.inference_config.top_logprobs,
8080
model_profile=self.inference_config.model_profile,
81+
request_timeout=self.inference_config.request_timeout,
8182
)
8283

8384
completions = [

src/fenic/_backends/local/semantic_operators/classify.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ def __init__(
4343
temperature: float,
4444
examples: Optional[ClassifyExampleCollection] = None,
4545
model_alias: Optional[ResolvedModelAlias] = None,
46+
request_timeout: Optional[float] = None,
4647
):
4748
self.classes = classes
4849
self.valid_labels = {class_def.label for class_def in classes}
@@ -59,6 +60,7 @@ def __init__(
5960
temperature=temperature,
6061
response_format=ResolvedResponseFormat.from_pydantic_model(self.output_model, generate_struct_type=False),
6162
model_profile=model_alias.profile if model_alias else None,
63+
request_timeout=request_timeout,
6264
),
6365
),
6466
examples,

src/fenic/_backends/local/semantic_operators/extract.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def __init__(
4949
max_output_tokens: int,
5050
temperature: float,
5151
model_alias: Optional[ResolvedModelAlias] = None,
52+
request_timeout: Optional[float] = None,
5253
):
5354
self.resolved_format = response_format
5455
super().__init__(
@@ -60,6 +61,7 @@ def __init__(
6061
temperature=temperature,
6162
response_format=response_format,
6263
model_profile=model_alias.profile if model_alias else None,
64+
request_timeout=request_timeout,
6365
),
6466
model=model,
6567
),

src/fenic/_backends/local/semantic_operators/map.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def __init__(
5252
model_alias: Optional[ResolvedModelAlias] = None,
5353
response_format: Optional[ResolvedResponseFormat] = None,
5454
examples: Optional[MapExampleCollection] = None,
55+
request_timeout: Optional[float] = None,
5556
):
5657
super().__init__(
5758
input,
@@ -63,6 +64,7 @@ def __init__(
6364
response_format=response_format,
6465
temperature=temperature,
6566
model_profile=model_alias.profile if model_alias else None,
67+
request_timeout=request_timeout,
6668
),
6769
),
6870
jinja_template=jinja2.Template(jinja_template),

src/fenic/_backends/local/semantic_operators/parse_pdf.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def __init__(
4949
describe_images: bool = False,
5050
model_alias: Optional[ResolvedModelAlias] = None,
5151
max_output_tokens: Optional[int] = None,
52+
request_timeout: Optional[float] = None,
5253
):
5354
self.page_separator = page_separator
5455
self.describe_images = describe_images
@@ -67,6 +68,7 @@ def __init__(
6768
max_output_tokens=max_output_tokens,
6869
temperature=1.0, # Use a higher temperature so gemini flash models can handle complex table formatting. For more info see the conversation here: https://discuss.ai.google.dev/t/gemini-2-0-flash-has-a-weird-bug/65119/26
6970
model_profile=model_alias.profile if model_alias else None,
71+
request_timeout=request_timeout,
7072
),
7173
),
7274
examples=None, # PDF parsing doesn't use examples

src/fenic/_backends/local/semantic_operators/predicate.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ def __init__(
4646
temperature: float,
4747
examples: Optional[PredicateExampleCollection] = None,
4848
model_alias: Optional[ResolvedModelAlias] = None,
49+
request_timeout: Optional[float] = None,
4950
):
5051
super().__init__(
5152
input,
@@ -56,6 +57,7 @@ def __init__(
5657
response_format=PREDICATE_FORMAT,
5758
temperature=temperature,
5859
model_profile=model_alias.profile if model_alias else None,
60+
request_timeout=request_timeout,
5961
),
6062
model=model,
6163
),

src/fenic/_backends/local/semantic_operators/summarize.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ def __init__(
4545
temperature: float,
4646
model: LanguageModel,
4747
model_alias: Optional[ResolvedModelAlias] = None,
48+
request_timeout: Optional[float] = None,
4849
):
4950
self.format = format
5051

@@ -56,6 +57,7 @@ def __init__(
5657
max_output_tokens=self.get_max_tokens(),
5758
temperature=temperature,
5859
model_profile=model_alias.profile if model_alias else None,
60+
request_timeout=request_timeout,
5961
),
6062
model=model,
6163
),

src/fenic/_backends/local/transpiler/expr_converter.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@ def sem_map_fn(batch: pl.Series) -> pl.Series:
547547
temperature=logical.temperature,
548548
response_format=logical.response_format,
549549
model_alias=logical.model_alias,
550+
request_timeout=logical.request_timeout,
550551
).execute()
551552

552553
column_exprs = [self._convert_expr(expr) for expr in logical.exprs]
@@ -646,6 +647,7 @@ def sem_ext_fn(batch: pl.Series) -> pl.Series:
646647
max_output_tokens=logical.max_tokens,
647648
temperature=logical.temperature,
648649
model_alias=logical.model_alias,
650+
request_timeout=logical.request_timeout,
649651
).execute()
650652

651653
return self._convert_expr(logical.expr).map_batches(
@@ -666,6 +668,7 @@ def sem_pred_fn(batch: pl.Series) -> pl.Series:
666668
examples=logical.examples,
667669
temperature=logical.temperature,
668670
model_alias=logical.model_alias,
671+
request_timeout=logical.request_timeout,
669672
).execute()
670673

671674
column_exprs = [self._convert_expr(expr) for expr in logical.exprs]
@@ -688,6 +691,7 @@ def sem_classify_fn(batch: pl.Series) -> pl.Series:
688691
temperature=logical.temperature,
689692
examples=logical.examples,
690693
model_alias=logical.model_alias,
694+
request_timeout=logical.request_timeout,
691695
).execute()
692696

693697
return self._convert_expr(logical.expr).map_batches(
@@ -703,6 +707,7 @@ def sem_sentiment_fn(batch: pl.Series) -> pl.Series:
703707
model=self.session_state.get_language_model(logical.model_alias),
704708
temperature=logical.temperature,
705709
model_alias=logical.model_alias,
710+
request_timeout=logical.request_timeout,
706711
).execute()
707712

708713
return self._convert_expr(logical.expr).map_batches(
@@ -719,7 +724,7 @@ def sem_summarize_fn(batch: pl.Series) -> pl.Series:
719724
format=logical.format,
720725
temperature=logical.temperature,
721726
model=self.session_state.get_language_model(logical.model_alias),
722-
727+
request_timeout=logical.request_timeout,
723728
).execute()
724729

725730
return self._convert_expr(logical.expr).map_batches(
@@ -736,6 +741,7 @@ def parse_pdf_fn(batch: pl.Series) -> pl.Series:
736741
describe_images=logical.describe_images,
737742
model_alias=logical.model_alias,
738743
max_output_tokens=logical.max_output_tokens,
744+
request_timeout=logical.request_timeout,
739745
).execute()
740746

741747
return self._convert_expr(logical.expr).map_batches(

src/fenic/_inference/anthropic/anthropic_provider.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
import logging
44

55
import anthropic
6+
import httpx
67

8+
from fenic._inference.request_utils import MAX_CLIENT_TIMEOUT
79
from fenic.core._inference.model_provider import ModelProviderClass
810

911
logger = logging.getLogger(__name__)
@@ -18,11 +20,11 @@ def name(self) -> str:
1820

1921
def create_client(self):
2022
"""Create an Anthropic sync client instance."""
21-
return anthropic.Client()
23+
return anthropic.Client(http_client=httpx.Client(timeout=MAX_CLIENT_TIMEOUT))
2224

2325
def create_aio_client(self):
2426
"""Create an Anthropic async client instance."""
25-
return anthropic.AsyncAnthropic()
27+
return anthropic.AsyncAnthropic(http_client=httpx.AsyncClient(timeout=MAX_CLIENT_TIMEOUT))
2628

2729
async def validate_api_key(self) -> None:
2830
"""Validate Anthropic API key by making a minimal completion request."""

0 commit comments

Comments
 (0)