langfun 0.1.1.dev20240828__py3-none-any.whl → 0.1.2.dev202408290804__py3-none-any.whl

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.
langfun/__init__.py CHANGED
@@ -75,4 +75,4 @@ CodeError = coding.CodeError
75
75
  # pylint: enable=g-import-not-at-top
76
76
  # pylint: enable=g-bad-import-order
77
77
 
78
- __version__ = "0.1.1"
78
+ __version__ = "0.1.2"
@@ -18,12 +18,29 @@ import functools
18
18
  import os
19
19
  from typing import Annotated, Any, Literal
20
20
 
21
- import google.generativeai as genai
22
21
  import langfun.core as lf
23
22
  from langfun.core import modalities as lf_modalities
24
23
  import pyglove as pg
25
24
 
26
25
 
26
+ try:
27
+ import google.generativeai as genai # pylint: disable=g-import-not-at-top
28
+ BlobDict = genai.types.BlobDict
29
+ GenerativeModel = genai.GenerativeModel
30
+ Completion = genai.types.Completion
31
+ GenerationConfig = genai.GenerationConfig
32
+ GenerateContentResponse = genai.types.GenerateContentResponse
33
+ ChatResponse = genai.types.ChatResponse
34
+ except ImportError:
35
+ genai = None
36
+ BlobDict = Any
37
+ GenerativeModel = Any
38
+ Completion = Any
39
+ GenerationConfig = Any
40
+ GenerateContentResponse = Any
41
+ ChatResponse = Any
42
+
43
+
27
44
  @lf.use_init_args(['model'])
28
45
  class GenAI(lf.LanguageModel):
29
46
  """Language models provided by Google GenAI."""
@@ -59,10 +76,16 @@ class GenAI(lf.LanguageModel):
59
76
 
60
77
  def _on_bound(self):
61
78
  super()._on_bound()
79
+ if genai is None:
80
+ raise RuntimeError(
81
+ 'Please install "langfun[llm-google-genai]" to use '
82
+ 'Google Generative AI models.'
83
+ )
62
84
  self.__dict__.pop('_api_initialized', None)
63
85
 
64
86
  @functools.cached_property
65
87
  def _api_initialized(self):
88
+ assert genai is not None
66
89
  api_key = self.api_key or os.environ.get('GOOGLE_API_KEY', None)
67
90
  if not api_key:
68
91
  raise ValueError(
@@ -78,6 +101,7 @@ class GenAI(lf.LanguageModel):
78
101
  @classmethod
79
102
  def dir(cls) -> list[str]:
80
103
  """Lists generative models."""
104
+ assert genai is not None
81
105
  return [
82
106
  m.name.lstrip('models/')
83
107
  for m in genai.list_models()
@@ -100,7 +124,7 @@ class GenAI(lf.LanguageModel):
100
124
 
101
125
  def _generation_config(self, options: lf.LMSamplingOptions) -> dict[str, Any]:
102
126
  """Creates generation config from langfun sampling options."""
103
- return genai.GenerationConfig(
127
+ return GenerationConfig(
104
128
  candidate_count=options.n,
105
129
  temperature=options.temperature,
106
130
  top_p=options.top_p,
@@ -111,7 +135,7 @@ class GenAI(lf.LanguageModel):
111
135
 
112
136
  def _content_from_message(
113
137
  self, prompt: lf.Message
114
- ) -> list[str | genai.types.BlobDict]:
138
+ ) -> list[str | BlobDict]:
115
139
  """Gets Evergreen formatted content from langfun message."""
116
140
  formatted = lf.UserMessage(prompt.text)
117
141
  formatted.source = prompt
@@ -131,7 +155,7 @@ class GenAI(lf.LanguageModel):
131
155
  if modality.is_text:
132
156
  chunk = modality.to_text()
133
157
  else:
134
- chunk = genai.types.BlobDict(
158
+ chunk = BlobDict(
135
159
  data=modality.to_bytes(),
136
160
  mime_type=modality.mime_type
137
161
  )
@@ -143,7 +167,7 @@ class GenAI(lf.LanguageModel):
143
167
  return chunks
144
168
 
145
169
  def _response_to_result(
146
- self, response: genai.types.GenerateContentResponse | pg.Dict
170
+ self, response: GenerateContentResponse | pg.Dict
147
171
  ) -> lf.LMSamplingResult:
148
172
  """Parses generative response into message."""
149
173
  samples = []
@@ -182,8 +206,8 @@ class _LegacyGenerativeModel(pg.Object):
182
206
 
183
207
  def generate_content(
184
208
  self,
185
- input_content: list[str | genai.types.BlobDict],
186
- generation_config: genai.GenerationConfig,
209
+ input_content: list[str | BlobDict],
210
+ generation_config: GenerationConfig,
187
211
  ) -> pg.Dict:
188
212
  """Generate content."""
189
213
  segments = []
@@ -195,7 +219,7 @@ class _LegacyGenerativeModel(pg.Object):
195
219
 
196
220
  @abc.abstractmethod
197
221
  def generate(
198
- self, prompt: str, generation_config: genai.GenerationConfig) -> pg.Dict:
222
+ self, prompt: str, generation_config: GenerationConfig) -> pg.Dict:
199
223
  """Generate response based on prompt."""
200
224
 
201
225
 
@@ -203,9 +227,10 @@ class _LegacyCompletionModel(_LegacyGenerativeModel):
203
227
  """Legacy GenAI completion model."""
204
228
 
205
229
  def generate(
206
- self, prompt: str, generation_config: genai.GenerationConfig
230
+ self, prompt: str, generation_config: GenerationConfig
207
231
  ) -> pg.Dict:
208
- completion: genai.types.Completion = genai.generate_text(
232
+ assert genai is not None
233
+ completion: Completion = genai.generate_text(
209
234
  model=f'models/{self.model}',
210
235
  prompt=prompt,
211
236
  temperature=generation_config.temperature,
@@ -227,9 +252,10 @@ class _LegacyChatModel(_LegacyGenerativeModel):
227
252
  """Legacy GenAI chat model."""
228
253
 
229
254
  def generate(
230
- self, prompt: str, generation_config: genai.GenerationConfig
255
+ self, prompt: str, generation_config: GenerationConfig
231
256
  ) -> pg.Dict:
232
- response: genai.types.ChatResponse = genai.chat(
257
+ assert genai is not None
258
+ response: ChatResponse = genai.chat(
233
259
  model=f'models/{self.model}',
234
260
  messages=prompt,
235
261
  temperature=generation_config.temperature,
@@ -253,8 +279,9 @@ class _ModelHub:
253
279
 
254
280
  def get(
255
281
  self, model_name: str
256
- ) -> genai.GenerativeModel | _LegacyGenerativeModel:
282
+ ) -> GenerativeModel | _LegacyGenerativeModel:
257
283
  """Gets a generative model by model id."""
284
+ assert genai is not None
258
285
  model = self._model_cache.get(model_name, None)
259
286
  if model is None:
260
287
  model_info = genai.get_model(f'models/{model_name}')
@@ -16,15 +16,31 @@
16
16
  import collections
17
17
  import functools
18
18
  import os
19
- from typing import Annotated, Any, cast
19
+ from typing import Annotated, Any
20
20
 
21
21
  import langfun.core as lf
22
22
  from langfun.core import modalities as lf_modalities
23
- import openai
24
- from openai import error as openai_error
25
- from openai import openai_object
26
23
  import pyglove as pg
27
24
 
25
+ try:
26
+ import openai # pylint: disable=g-import-not-at-top
27
+
28
+ if hasattr(openai, 'error'):
29
+ # For lower versions.
30
+ ServiceUnavailableError = openai.error.ServiceUnavailableError
31
+ RateLimitError = openai.error.RateLimitError
32
+ APITimeoutError = (
33
+ openai.error.APIError,
34
+ '.*The server had an error processing your request'
35
+ )
36
+ else:
37
+ # For higher versions.
38
+ ServiceUnavailableError = getattr(openai, 'InternalServerError')
39
+ RateLimitError = getattr(openai, 'RateLimitError')
40
+ APITimeoutError = getattr(openai, 'APITimeoutError')
41
+ except ImportError:
42
+ openai = None
43
+
28
44
 
29
45
  # From https://platform.openai.com/settings/organization/limits
30
46
  _DEFAULT_TPM = 250000
@@ -119,6 +135,10 @@ class OpenAI(lf.LanguageModel):
119
135
  def _on_bound(self):
120
136
  super()._on_bound()
121
137
  self.__dict__.pop('_api_initialized', None)
138
+ if openai is None:
139
+ raise RuntimeError(
140
+ 'Please install "langfun[llm-openai]" to use OpenAI models.'
141
+ )
122
142
 
123
143
  @functools.cached_property
124
144
  def _api_initialized(self):
@@ -149,6 +169,7 @@ class OpenAI(lf.LanguageModel):
149
169
 
150
170
  @classmethod
151
171
  def dir(cls):
172
+ assert openai is not None
152
173
  return openai.Model.list()
153
174
 
154
175
  @property
@@ -195,11 +216,11 @@ class OpenAI(lf.LanguageModel):
195
216
  ) -> list[lf.LMSamplingResult]:
196
217
 
197
218
  def _open_ai_completion(prompts):
219
+ assert openai is not None
198
220
  response = openai.Completion.create(
199
221
  prompt=[p.text for p in prompts],
200
222
  **self._get_request_args(self.sampling_options),
201
223
  )
202
- response = cast(openai_object.OpenAIObject, response)
203
224
  # Parse response.
204
225
  samples_by_index = collections.defaultdict(list)
205
226
  for choice in response.choices:
@@ -222,12 +243,9 @@ class OpenAI(lf.LanguageModel):
222
243
  _open_ai_completion,
223
244
  [prompts],
224
245
  retry_on_errors=(
225
- openai_error.ServiceUnavailableError,
226
- openai_error.RateLimitError,
227
- # Handling transient OpenAI server error (code 500). Check out
228
- # https://platform.openai.com/docs/guides/error-codes/error-codes
229
- (openai_error.APIError,
230
- '.*The server had an error processing your request'),
246
+ ServiceUnavailableError,
247
+ RateLimitError,
248
+ APITimeoutError,
231
249
  ),
232
250
  )[0]
233
251
 
@@ -292,10 +310,8 @@ class OpenAI(lf.LanguageModel):
292
310
  )
293
311
  messages.append(dict(role='user', content=_content_from_message(prompt)))
294
312
 
295
- response = cast(
296
- openai_object.OpenAIObject,
297
- openai.ChatCompletion.create(messages=messages, **request_args)
298
- )
313
+ assert openai is not None
314
+ response = openai.ChatCompletion.create(messages=messages, **request_args)
299
315
 
300
316
  samples = []
301
317
  for choice in response.choices:
@@ -330,8 +346,9 @@ class OpenAI(lf.LanguageModel):
330
346
  _open_ai_chat_completion,
331
347
  prompts,
332
348
  retry_on_errors=(
333
- openai_error.ServiceUnavailableError,
334
- openai_error.RateLimitError,
349
+ ServiceUnavailableError,
350
+ RateLimitError,
351
+ APITimeoutError
335
352
  ),
336
353
  )
337
354
 
@@ -17,11 +17,28 @@ import functools
17
17
  import os
18
18
  from typing import Annotated, Any
19
19
 
20
- from google.auth import credentials as credentials_lib
21
20
  import langfun.core as lf
22
21
  from langfun.core import modalities as lf_modalities
23
22
  import pyglove as pg
24
23
 
24
+ try:
25
+ # pylint: disable=g-import-not-at-top
26
+ from google.auth import credentials as credentials_lib
27
+ import vertexai
28
+ from google.cloud.aiplatform import models as aiplatform_models
29
+ from vertexai import generative_models
30
+ from vertexai import language_models
31
+ # pylint: enable=g-import-not-at-top
32
+
33
+ Credentials = credentials_lib.Credentials
34
+ except ImportError:
35
+ credentials_lib = None # pylint: disable=invalid-name
36
+ vertexai = None
37
+ generative_models = None
38
+ language_models = None
39
+ aiplatform_models = None
40
+ Credentials = Any
41
+
25
42
 
26
43
  SUPPORTED_MODELS_AND_SETTINGS = {
27
44
  'gemini-1.5-pro-001': pg.Dict(api='gemini', rpm=50),
@@ -78,7 +95,7 @@ class VertexAI(lf.LanguageModel):
78
95
  ] = None
79
96
 
80
97
  credentials: Annotated[
81
- credentials_lib.Credentials | None,
98
+ Credentials | None,
82
99
  (
83
100
  'Credentials to use. If None, the default credentials to the '
84
101
  'environment will be used.'
@@ -93,6 +110,10 @@ class VertexAI(lf.LanguageModel):
93
110
  def _on_bound(self):
94
111
  super()._on_bound()
95
112
  self.__dict__.pop('_api_initialized', None)
113
+ if generative_models is None:
114
+ raise RuntimeError(
115
+ 'Please install "langfun[llm-google-vertex]" to use Vertex AI models.'
116
+ )
96
117
 
97
118
  @functools.cached_property
98
119
  def _api_initialized(self):
@@ -112,7 +133,7 @@ class VertexAI(lf.LanguageModel):
112
133
 
113
134
  credentials = self.credentials
114
135
  # Placeholder for Google-internal credentials.
115
- import vertexai
136
+ assert vertexai is not None
116
137
  vertexai.init(project=project, location=location, credentials=credentials)
117
138
  return True
118
139
 
@@ -138,7 +159,7 @@ class VertexAI(lf.LanguageModel):
138
159
  self, prompt: lf.Message, options: lf.LMSamplingOptions
139
160
  ) -> Any: # generative_models.GenerationConfig
140
161
  """Creates generation config from langfun sampling options."""
141
- from vertexai import generative_models
162
+ assert generative_models is not None
142
163
  # Users could use `metadata_json_schema` to pass additional
143
164
  # request arguments.
144
165
  json_schema = prompt.metadata.get('json_schema')
@@ -169,7 +190,7 @@ class VertexAI(lf.LanguageModel):
169
190
  self, prompt: lf.Message
170
191
  ) -> list[str | Any]:
171
192
  """Gets generation input from langfun message."""
172
- from vertexai import generative_models
193
+ assert generative_models is not None
173
194
  chunks = []
174
195
 
175
196
  for lf_chunk in prompt.chunk():
@@ -296,8 +317,8 @@ class VertexAI(lf.LanguageModel):
296
317
 
297
318
  def _sample_endpoint_model(self, prompt: lf.Message) -> lf.LMSamplingResult:
298
319
  """Samples a text generation model."""
299
- from google.cloud.aiplatform import models
300
- model = models.Endpoint(self.endpoint_name)
320
+ assert aiplatform_models is not None
321
+ model = aiplatform_models.Endpoint(self.endpoint_name)
301
322
  # TODO(chengrun): Add support for stop_sequences.
302
323
  predict_options = dict(
303
324
  temperature=self.sampling_options.temperature
@@ -337,7 +358,7 @@ class _ModelHub:
337
358
  """Gets a generative model by model id."""
338
359
  model = self._generative_model_cache.get(model_id, None)
339
360
  if model is None:
340
- from vertexai import generative_models
361
+ assert generative_models is not None
341
362
  model = generative_models.GenerativeModel(model_id)
342
363
  self._generative_model_cache[model_id] = model
343
364
  return model
@@ -348,7 +369,7 @@ class _ModelHub:
348
369
  """Gets a text generation model by model id."""
349
370
  model = self._text_generation_model_cache.get(model_id, None)
350
371
  if model is None:
351
- from vertexai import language_models
372
+ assert language_models is not None
352
373
  model = language_models.TextGenerationModel.from_pretrained(model_id)
353
374
  self._text_generation_model_cache[model_id] = model
354
375
  return model
@@ -15,9 +15,21 @@
15
15
 
16
16
  import functools
17
17
  import io
18
+ from typing import Any
18
19
 
19
20
  from langfun.core.modalities import mime
20
- from PIL import Image as pil_image
21
+
22
+ try:
23
+ from PIL import Image as pil_image # pylint: disable=g-import-not-at-top
24
+ PILImage = pil_image.Image
25
+ pil_open = pil_image.open
26
+ except ImportError:
27
+ PILImage = Any
28
+
29
+ def pil_open(*unused_args, **unused_kwargs):
30
+ raise RuntimeError(
31
+ 'Please install "langfun[mime-pil]" to enable PIL image support.'
32
+ )
21
33
 
22
34
 
23
35
  class Image(mime.Mime):
@@ -34,14 +46,14 @@ class Image(mime.Mime):
34
46
 
35
47
  @functools.cached_property
36
48
  def size(self) -> tuple[int, int]:
37
- img = pil_image.open(io.BytesIO(self.to_bytes()))
49
+ img = pil_open(io.BytesIO(self.to_bytes()))
38
50
  return img.size
39
51
 
40
- def to_pil_image(self) -> pil_image.Image:
41
- return pil_image.open(io.BytesIO(self.to_bytes()))
52
+ def to_pil_image(self) -> PILImage: # pytype: disable=invalid-annotation
53
+ return pil_open(io.BytesIO(self.to_bytes()))
42
54
 
43
55
  @classmethod
44
- def from_pil_image(cls, img: pil_image.Image) -> 'Image':
56
+ def from_pil_image(cls, img: PILImage) -> 'Image': # pytype: disable=invalid-annotation
45
57
  buf = io.BytesIO()
46
58
  img.save(buf, format='PNG')
47
59
  return cls.from_bytes(buf.getvalue())
@@ -17,11 +17,20 @@ import base64
17
17
  import functools
18
18
  from typing import Annotated, Iterable, Type, Union
19
19
  import langfun.core as lf
20
- import magic
21
20
  import pyglove as pg
22
21
  import requests
23
22
 
24
23
 
24
+ try:
25
+ import magic # pylint: disable=g-import-not-at-top
26
+ from_buffer = magic.from_buffer
27
+ except ImportError:
28
+ def from_buffer(*unused_args, **unused_kwargs):
29
+ raise RuntimeError(
30
+ 'Please install "langfun[mime-auto]" to enable automatic MIME support.'
31
+ )
32
+
33
+
25
34
  class Mime(lf.Modality):
26
35
  """Base for MIME data."""
27
36
 
@@ -38,7 +47,7 @@ class Mime(lf.Modality):
38
47
  @functools.cached_property
39
48
  def mime_type(self) -> str:
40
49
  """Returns the MIME type."""
41
- mime = magic.from_buffer((self.to_bytes()), mime=True)
50
+ mime = from_buffer((self.to_bytes()), mime=True)
42
51
  if (
43
52
  self.MIME_PREFIX
44
53
  and not mime.lower().startswith(self.MIME_PREFIX)
@@ -136,14 +145,14 @@ class Mime(lf.Modality):
136
145
  def from_uri(cls, uri: str, **kwargs) -> 'Mime':
137
146
  if cls is Mime:
138
147
  content = cls.download(uri)
139
- mime = magic.from_buffer(content, mime=True).lower()
148
+ mime = from_buffer(content, mime=True).lower()
140
149
  return cls.class_from_mime_type(mime)(uri=uri, content=content, **kwargs)
141
150
  return cls(uri=uri, content=None, **kwargs)
142
151
 
143
152
  @classmethod
144
153
  def from_bytes(cls, content: bytes | str, **kwargs) -> 'Mime':
145
154
  if cls is Mime:
146
- mime = magic.from_buffer(content, mime=True).lower()
155
+ mime = from_buffer(content, mime=True).lower()
147
156
  return cls.class_from_mime_type(mime)(content=content, **kwargs)
148
157
  return cls(content=content, **kwargs)
149
158
 
@@ -30,10 +30,15 @@ class Xlsx(mime.Mime):
30
30
  )
31
31
 
32
32
  def to_html(self) -> str:
33
- import pandas as pd # pylint: disable=g-import-not-at-top
34
-
35
- df = pd.read_excel(io.BytesIO(self.to_bytes()))
36
- return df.to_html()
33
+ try:
34
+ import pandas as pd # pylint: disable=g-import-not-at-top
35
+ import openpyxl # pylint: disable=g-import-not-at-top, unused-import
36
+ df = pd.read_excel(io.BytesIO(self.to_bytes()))
37
+ return df.to_html()
38
+ except ImportError as e:
39
+ raise RuntimeError(
40
+ 'Please install "langfun[mime-xlsx]" to enable XLSX support.'
41
+ ) from e
37
42
 
38
43
  def _repr_html_(self) -> str:
39
44
  return self.to_html()
@@ -58,10 +63,14 @@ class Docx(mime.Mime):
58
63
  )
59
64
 
60
65
  def to_xml(self) -> str:
61
- import docx # pylint: disable=g-import-not-at-top
62
-
63
- doc = docx.Document(io.BytesIO(self.to_bytes()))
64
- return str(doc.element.xml)
66
+ try:
67
+ import docx # pylint: disable=g-import-not-at-top
68
+ doc = docx.Document(io.BytesIO(self.to_bytes()))
69
+ return str(doc.element.xml)
70
+ except ImportError as e:
71
+ raise RuntimeError(
72
+ 'Please install "langfun[mime-docx]" to enable Docx support.'
73
+ ) from e
65
74
 
66
75
  def _repr_html_(self) -> str:
67
76
  return self.to_xml()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: langfun
3
- Version: 0.1.1.dev20240828
3
+ Version: 0.1.2.dev202408290804
4
4
  Summary: Langfun: Language as Functions.
5
5
  Home-page: https://github.com/google/langfun
6
6
  Author: Langfun Authors
@@ -21,19 +21,54 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
21
  Classifier: Topic :: Software Development :: Libraries
22
22
  Description-Content-Type: text/markdown
23
23
  License-File: LICENSE
24
- Requires-Dist: google-cloud-aiplatform>=1.5.0
25
- Requires-Dist: google-generativeai>=0.3.2
24
+ Requires-Dist: pyglove>=0.4.5.dev20240824
26
25
  Requires-Dist: jinja2>=3.1.2
27
- Requires-Dist: openai==0.27.2
28
- Requires-Dist: openpyxl>=3.1.0
29
- Requires-Dist: pandas>=2.0.3
30
- Requires-Dist: pyglove>=0.4.5.dev20240423
31
- Requires-Dist: python-docx>=0.8.11
32
- Requires-Dist: python-magic>=0.4.27
33
26
  Requires-Dist: requests>=2.31.0
34
- Requires-Dist: termcolor==1.1.0
35
- Requires-Dist: tqdm>=4.64.1
36
- Requires-Dist: pillow>=10.0.0
27
+ Provides-Extra: all
28
+ Requires-Dist: pyglove>=0.4.5.dev20240824; extra == "all"
29
+ Requires-Dist: jinja2>=3.1.2; extra == "all"
30
+ Requires-Dist: requests>=2.31.0; extra == "all"
31
+ Requires-Dist: termcolor==1.1.0; extra == "all"
32
+ Requires-Dist: tqdm>=4.64.1; extra == "all"
33
+ Requires-Dist: google-cloud-aiplatform>=1.5.0; extra == "all"
34
+ Requires-Dist: google-generativeai>=0.3.2; extra == "all"
35
+ Requires-Dist: openai>=0.27.2; extra == "all"
36
+ Requires-Dist: python-magic>=0.4.27; extra == "all"
37
+ Requires-Dist: python-docx>=0.8.11; extra == "all"
38
+ Requires-Dist: pillow>=10.0.0; extra == "all"
39
+ Requires-Dist: openpyxl>=3.1.0; extra == "all"
40
+ Requires-Dist: pandas>=2.0.3; extra == "all"
41
+ Provides-Extra: llm
42
+ Requires-Dist: google-cloud-aiplatform>=1.5.0; extra == "llm"
43
+ Requires-Dist: google-generativeai>=0.3.2; extra == "llm"
44
+ Requires-Dist: openai>=0.27.2; extra == "llm"
45
+ Provides-Extra: llm-google
46
+ Requires-Dist: google-cloud-aiplatform>=1.5.0; extra == "llm-google"
47
+ Requires-Dist: google-generativeai>=0.3.2; extra == "llm-google"
48
+ Provides-Extra: llm-google-genai
49
+ Requires-Dist: google-generativeai>=0.3.2; extra == "llm-google-genai"
50
+ Provides-Extra: llm-google-vertex
51
+ Requires-Dist: google-cloud-aiplatform>=1.5.0; extra == "llm-google-vertex"
52
+ Provides-Extra: llm-openai
53
+ Requires-Dist: openai>=0.27.2; extra == "llm-openai"
54
+ Provides-Extra: mime
55
+ Requires-Dist: python-magic>=0.4.27; extra == "mime"
56
+ Requires-Dist: python-docx>=0.8.11; extra == "mime"
57
+ Requires-Dist: pillow>=10.0.0; extra == "mime"
58
+ Requires-Dist: openpyxl>=3.1.0; extra == "mime"
59
+ Requires-Dist: pandas>=2.0.3; extra == "mime"
60
+ Provides-Extra: mime-auto
61
+ Requires-Dist: python-magic>=0.4.27; extra == "mime-auto"
62
+ Provides-Extra: mime-docx
63
+ Requires-Dist: python-docx>=0.8.11; extra == "mime-docx"
64
+ Provides-Extra: mime-pil
65
+ Requires-Dist: pillow>=10.0.0; extra == "mime-pil"
66
+ Provides-Extra: mime-xlsx
67
+ Requires-Dist: openpyxl>=3.1.0; extra == "mime-xlsx"
68
+ Requires-Dist: pandas>=2.0.3; extra == "mime-xlsx"
69
+ Provides-Extra: ui
70
+ Requires-Dist: termcolor==1.1.0; extra == "ui"
71
+ Requires-Dist: tqdm>=4.64.1; extra == "ui"
37
72
 
38
73
  <div align="center">
39
74
  <img src="https://raw.githubusercontent.com/google/langfun/main/docs/_static/logo.svg" width="520px" alt="logo"></img>
@@ -152,16 +187,45 @@ See [Langfun 101](https://colab.research.google.com/github/google/langfun/blob/m
152
187
 
153
188
  ## Install
154
189
 
190
+ Langfun offers a range of features through [Extras](https://packaging.python.org/en/latest/tutorials/installing-packages/#installing-extras), allowing users to install only what they need. The minimal installation of Langfun requires only [PyGlove](https://github.com/google/pyglove), [Jinja2](https://github.com/pallets/jinja/), and [requests](https://github.com/psf/requests). To install Langfun with its minimal dependencies, use:
191
+
155
192
  ```
156
193
  pip install langfun
157
194
  ```
158
195
 
159
- Or install nightly build with:
196
+ For a complete installation with all dependencies, use:
160
197
 
161
198
  ```
162
- pip install langfun --pre
199
+ pip install langfun[all]
163
200
  ```
164
201
 
202
+ To install a nightly build, include the `--pre` flag, like this:
203
+
204
+ ```
205
+ pip install langfun[all] --pre
206
+ ```
165
207
 
208
+ If you want to customize your installation, you can select specific features using package names like `langfun[X1, X2, ..., Xn]`, where `Xi` corresponds to a tag from the list below:
209
+
210
+ | Tag | Description |
211
+ | ------------------- | ---------------------------------------- |
212
+ | all | All Langfun features. |
213
+ | llm | All supported LLMs. |
214
+ | llm-google | All supported Google-powered LLMs. |
215
+ | llm-google-vertexai | LLMs powered by Google Cloud VertexAI |
216
+ | llm-google-genai | LLMs powered by Google Generative AI API |
217
+ | llm-openai | LLMs powered by OpenAI |
218
+ | mime | All MIME supports. |
219
+ | mime-auto | Automatic MIME type detection. |
220
+ | mime-docx | DocX format support. |
221
+ | mime-pil | Image support for PIL. |
222
+ | mime-xlsx | XlsX format support. |
223
+ | ui | UI enhancements |
224
+
225
+
226
+ For example, to install a nightly build that includes Google-powered LLMs, full modality support, and UI enhancements, use:
227
+ ```
228
+ pip install langfun[llm-google,mime,ui] --pre
229
+ ```
166
230
 
167
231
  *Disclaimer: this is not an officially supported Google product.*
@@ -1,4 +1,4 @@
1
- langfun/__init__.py,sha256=ZqERg4fvvtFwr5L41Lfev9FSuCBm8PbQrZmcKvvloxE,2274
1
+ langfun/__init__.py,sha256=mCES7t3R7Z-ZQYvG38-yrVqZubrXNfGCa8tI5HGB7mE,2274
2
2
  langfun/core/__init__.py,sha256=r86kuy-BiJIveqnXx5OklUUXtMG3q79nWRBum6zFOCQ,4835
3
3
  langfun/core/component.py,sha256=Icyoj9ICoJoK2r2PHbrFXbxnseOr9QZZOvKWklLWNo8,10276
4
4
  langfun/core/component_test.py,sha256=q15Xn51cVTu2RKxZ9U5VQgT3bm6RQ4638bKhWBtvW5o,8220
@@ -57,17 +57,17 @@ langfun/core/llms/anthropic.py,sha256=Gon3fOi31RhZFgNd0ijyTnKnUdp9hrWrCoSXyO4UaL
57
57
  langfun/core/llms/anthropic_test.py,sha256=T-swuMkfnlgs8Fpif4rtXs579exGk0TsbLMirXDZCkg,5533
58
58
  langfun/core/llms/fake.py,sha256=gCHBYBLvBCsC78HI1hpoqXCS-p1FMTgY1P1qh_sGBPk,3070
59
59
  langfun/core/llms/fake_test.py,sha256=sIl_Mg7nFVjaN7AJhYCpA_qzDJpSnJzkazepGXpfQQg,7338
60
- langfun/core/llms/google_genai.py,sha256=Rl5a5CyF_6Y0BYYArKk8yMaenv1rH3MUQLy6b3dfMRI,10202
60
+ langfun/core/llms/google_genai.py,sha256=OYrlKIEY57CFWYwndvEdhXLwffNvDwKXyy9ULZTNeYI,10885
61
61
  langfun/core/llms/google_genai_test.py,sha256=iTISk3tJ4-3gjWmzcKQhEbH3ke4AkEiCu8rAGtB7SvU,7535
62
62
  langfun/core/llms/groq.py,sha256=pqtyOZ_1_OJMOg8xATWT_B_SVbuT9nMRf4VkH9GzW8g,6308
63
63
  langfun/core/llms/groq_test.py,sha256=GYF_Qtq5S1H1TrKH38t6_lkdroqT7v-joYLDKnmS9e0,5274
64
64
  langfun/core/llms/llama_cpp.py,sha256=9tXQntSCDtjTF3bnyJrAPCr4N6wycy5nXYvp9uduygE,2843
65
65
  langfun/core/llms/llama_cpp_test.py,sha256=MWO_qaOeKjRniGjcaWPDScd7HPaIJemqUZoslrt4FPs,1806
66
- langfun/core/llms/openai.py,sha256=lRfR2iim7OdzMCJCf1DXB5YVfSwflvUucMWY3dsMaRA,15798
66
+ langfun/core/llms/openai.py,sha256=aZ5RgRBomVhBtzJtGYu9EM-qm07WEDcJr127VGpc_Sg,16161
67
67
  langfun/core/llms/openai_test.py,sha256=02KeysRppXcAwA4SBUow8hKolFiEU9_lTSdlVHZletM,17518
68
68
  langfun/core/llms/rest.py,sha256=laopuq-zD8V-3Y6eFDngftHEbE66VlUkCD2-rvvRaLU,3388
69
69
  langfun/core/llms/rest_test.py,sha256=NZ3Nf0XQVpT9kLP5cBVo_yBHLI7vWTYhWQxYEJVMGs4,3472
70
- langfun/core/llms/vertexai.py,sha256=tXAnP357XhcsETTnk6M-hH4xyFi7tk6fsaf3tjzsY6E,14501
70
+ langfun/core/llms/vertexai.py,sha256=mEQVwO3Kf3rGRmsI-qKrV6vg0hYy6OH1lEVOM81cb3U,15134
71
71
  langfun/core/llms/vertexai_test.py,sha256=EPR-mB2hNUpvpf7E8m_k5bh04epdQTVUuYU6hPgZyu8,10321
72
72
  langfun/core/llms/cache/__init__.py,sha256=QAo3InUMDM_YpteNnVCSejI4zOsnjSMWKJKzkb3VY64,993
73
73
  langfun/core/llms/cache/base.py,sha256=rt3zwmyw0y9jsSGW-ZbV1vAfLxQ7_3AVk0l2EySlse4,3918
@@ -79,11 +79,11 @@ langfun/core/memories/conversation_history_test.py,sha256=AaW8aNoFjxNusanwJDV0r3
79
79
  langfun/core/modalities/__init__.py,sha256=F8P72IwFiTpEseTR2tYEJyQMlDW7fd9csvGJquLKJNg,1269
80
80
  langfun/core/modalities/audio.py,sha256=Qxo7bYjLKQ1gVJVomr9RqR2SvxY826QgXhTzzk437Sk,952
81
81
  langfun/core/modalities/audio_test.py,sha256=gWCB9h3FyrdGqro3ajBXqkw0lU0W1sBjOOq6wZbl7Fg,2027
82
- langfun/core/modalities/image.py,sha256=uBSAwExnSD4MevhK9Z4qExPlLVFBQLUfjPOAldtWFOI,1387
82
+ langfun/core/modalities/image.py,sha256=DyVV17Ii-vJmwA7Mo23B40m4VxZg_WXc0KPKN8Q4Mlc,1756
83
83
  langfun/core/modalities/image_test.py,sha256=A0aYblxpnKABDgm2OVPxF8iRq4qFVanM9TPcaewkAgA,3774
84
- langfun/core/modalities/mime.py,sha256=7oYvwYZHb3uhjiL2rF6kvQWsWufY0UXl72wfDXC59ys,5918
84
+ langfun/core/modalities/mime.py,sha256=-BEIAcIGzPdPgwUZ2yqFj6NGsBYGCiqeNqIWVeaNnTI,6164
85
85
  langfun/core/modalities/mime_test.py,sha256=kmRiPP-3Py02NnKPu0oPexSIJ-MXaaE2UYY82ga0TV8,2913
86
- langfun/core/modalities/ms_office.py,sha256=jOidMSdWCaV9RILpGz8VJkpTSpHJNoirD53jzQvcytM,3388
86
+ langfun/core/modalities/ms_office.py,sha256=_dUgUCfK-hsEMOjgA_q3hUgKC4n8iAufKy7Sh2Gs1Jo,3780
87
87
  langfun/core/modalities/ms_office_test.py,sha256=d_NZ0QU23NydenYZgNj6YxgO5ZYzjg-HCbglsVJGp04,87866
88
88
  langfun/core/modalities/pdf.py,sha256=mfaeCbUA4JslFVTARiJh8hW7imvL4tLVw9gUhO5bAZA,727
89
89
  langfun/core/modalities/pdf_test.py,sha256=KE40zJD3Whe6ty2OULkp1J8jwLmB4ZjGXlGekluTP48,1952
@@ -119,8 +119,8 @@ langfun/core/templates/demonstration.py,sha256=vCrgYubdZM5Umqcgp8NUVGXgr4P_c-fik
119
119
  langfun/core/templates/demonstration_test.py,sha256=SafcDQ0WgI7pw05EmPI2S4v1t3ABKzup8jReCljHeK4,2162
120
120
  langfun/core/templates/selfplay.py,sha256=yhgrJbiYwq47TgzThmHrDQTF4nDrTI09CWGhuQPNv-s,2273
121
121
  langfun/core/templates/selfplay_test.py,sha256=rBW2Qr8yi-aWYwoTwRR-n1peKyMX9QXPZXURjLgoiRs,2264
122
- langfun-0.1.1.dev20240828.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
123
- langfun-0.1.1.dev20240828.dist-info/METADATA,sha256=zPpmQkxNgUcb7ilrk9JmSBVnq_ISkkujk3bPQ2nPKDQ,5234
124
- langfun-0.1.1.dev20240828.dist-info/WHEEL,sha256=UvcQYKBHoFqaQd6LKyqHw9fxEolWLQnlzP0h_LgJAfI,91
125
- langfun-0.1.1.dev20240828.dist-info/top_level.txt,sha256=RhlEkHxs1qtzmmtWSwYoLVJAc1YrbPtxQ52uh8Z9VvY,8
126
- langfun-0.1.1.dev20240828.dist-info/RECORD,,
122
+ langfun-0.1.2.dev202408290804.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
123
+ langfun-0.1.2.dev202408290804.dist-info/METADATA,sha256=9jwTsXU16vvdZQY6zaFH_MYgIdGknEjk_wR8G539Mt0,8825
124
+ langfun-0.1.2.dev202408290804.dist-info/WHEEL,sha256=UvcQYKBHoFqaQd6LKyqHw9fxEolWLQnlzP0h_LgJAfI,91
125
+ langfun-0.1.2.dev202408290804.dist-info/top_level.txt,sha256=RhlEkHxs1qtzmmtWSwYoLVJAc1YrbPtxQ52uh8Z9VvY,8
126
+ langfun-0.1.2.dev202408290804.dist-info/RECORD,,