langroid 0.45.10__py3-none-any.whl → 0.46.0__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.
@@ -10,6 +10,7 @@ from openai import AzureOpenAI, OpenAI
10
10
 
11
11
  from langroid.embedding_models.base import EmbeddingModel, EmbeddingModelsConfig
12
12
  from langroid.exceptions import LangroidImportError
13
+ from langroid.language_models.openai_gpt import LangDBParams
13
14
  from langroid.mytypes import Embeddings
14
15
  from langroid.parsing.utils import batched
15
16
 
@@ -24,6 +25,7 @@ class OpenAIEmbeddingsConfig(EmbeddingModelsConfig):
24
25
  organization: str = ""
25
26
  dims: int = 1536
26
27
  context_length: int = 8192
28
+ langdb_params: LangDBParams = LangDBParams()
27
29
 
28
30
  class Config:
29
31
  # enable auto-loading of env vars with OPENAI_ prefix, e.g.
@@ -136,11 +138,13 @@ class EmbeddingFunctionCallable:
136
138
  """
137
139
  embeds = []
138
140
  if isinstance(self.embed_model, (OpenAIEmbeddings, AzureOpenAIEmbeddings)):
139
- tokenized_texts = self.embed_model.truncate_texts(input)
141
+ # Truncate texts to context length while preserving text format
142
+ truncated_texts = self.embed_model.truncate_texts(input)
140
143
 
141
- for batch in batched(tokenized_texts, self.batch_size):
144
+ # Process in batches
145
+ for batch in batched(truncated_texts, self.batch_size):
142
146
  result = self.embed_model.client.embeddings.create(
143
- input=batch, model=self.embed_model.config.model_name
147
+ input=batch, model=self.embed_model.config.model_name # type: ignore
144
148
  )
145
149
  batch_embeds = [d.embedding for d in result.data]
146
150
  embeds.extend(batch_embeds)
@@ -183,30 +187,66 @@ class OpenAIEmbeddings(EmbeddingModel):
183
187
  super().__init__()
184
188
  self.config = config
185
189
  load_dotenv()
186
- self.config.api_key = os.getenv("OPENAI_API_KEY", "")
190
+
191
+ # Check if using LangDB
192
+ self.is_langdb = self.config.model_name.startswith("langdb/")
193
+
194
+ if self.is_langdb:
195
+ self.config.model_name = self.config.model_name.replace("langdb/", "")
196
+ self.config.api_base = self.config.langdb_params.base_url
197
+ project_id = self.config.langdb_params.project_id
198
+ if project_id:
199
+ self.config.api_base += "/" + project_id + "/v1"
200
+ self.config.api_key = self.config.langdb_params.api_key
201
+
202
+ if not self.config.api_key:
203
+ self.config.api_key = os.getenv("OPENAI_API_KEY", "")
204
+
187
205
  self.config.organization = os.getenv("OPENAI_ORGANIZATION", "")
206
+
188
207
  if self.config.api_key == "":
189
- raise ValueError(
190
- """OPENAI_API_KEY env variable must be set to use
191
- OpenAIEmbeddings. Please set the OPENAI_API_KEY value
192
- in your .env file.
193
- """
194
- )
195
- self.client = OpenAI(base_url=self.config.api_base, api_key=self.config.api_key)
208
+ if self.is_langdb:
209
+ raise ValueError(
210
+ """
211
+ LANGDB_API_KEY must be set in .env or your environment
212
+ to use OpenAIEmbeddings via LangDB.
213
+ """
214
+ )
215
+ else:
216
+ raise ValueError(
217
+ """
218
+ OPENAI_API_KEY must be set in .env or your environment
219
+ to use OpenAIEmbeddings.
220
+ """
221
+ )
222
+
223
+ self.client = OpenAI(
224
+ base_url=self.config.api_base,
225
+ api_key=self.config.api_key,
226
+ organization=self.config.organization,
227
+ )
228
+ model_for_tokenizer = self.config.model_name
229
+ if model_for_tokenizer.startswith("openai/"):
230
+ self.config.model_name = model_for_tokenizer.replace("openai/", "")
196
231
  self.tokenizer = tiktoken.encoding_for_model(self.config.model_name)
197
232
 
198
- def truncate_texts(self, texts: List[str]) -> List[List[int]]:
233
+ def truncate_texts(self, texts: List[str]) -> List[str] | List[List[int]]:
199
234
  """
200
235
  Truncate texts to the embedding model's context length.
201
236
  TODO: Maybe we should show warning, and consider doing T5 summarization?
202
237
  """
203
- return [
238
+ truncated_tokens = [
204
239
  self.tokenizer.encode(text, disallowed_special=())[
205
240
  : self.config.context_length
206
241
  ]
207
242
  for text in texts
208
243
  ]
209
244
 
245
+ if self.is_langdb:
246
+ # LangDB embedding endpt only works with strings, not tokens
247
+ return [self.tokenizer.decode(tokens) for tokens in truncated_tokens]
248
+ return truncated_tokens
249
+
210
250
  def embedding_fn(self) -> Callable[[List[str]], Embeddings]:
211
251
  return EmbeddingFunctionCallable(self, self.config.batch_size)
212
252
 
@@ -256,7 +296,7 @@ class AzureOpenAIEmbeddings(EmbeddingModel):
256
296
  )
257
297
  self.tokenizer = tiktoken.encoding_for_model(self.config.model_name)
258
298
 
259
- def truncate_texts(self, texts: List[str]) -> List[List[int]]:
299
+ def truncate_texts(self, texts: List[str]) -> List[str] | List[List[int]]:
260
300
  """
261
301
  Truncate texts to the embedding model's context length.
262
302
  TODO: Maybe we should show warning, and consider doing T5 summarization?
@@ -66,7 +66,7 @@ from langroid.language_models.utils import (
66
66
  retry_with_exponential_backoff,
67
67
  )
68
68
  from langroid.parsing.parse_json import parse_imperfect_json
69
- from langroid.pydantic_v1 import BaseModel
69
+ from langroid.pydantic_v1 import BaseModel, BaseSettings
70
70
  from langroid.utils.configuration import settings
71
71
  from langroid.utils.constants import Colors
72
72
  from langroid.utils.system import friendly_error
@@ -82,9 +82,13 @@ DEEPSEEK_BASE_URL = "https://api.deepseek.com/v1"
82
82
  OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1"
83
83
  GEMINI_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/openai"
84
84
  GLHF_BASE_URL = "https://glhf.chat/api/openai/v1"
85
+ LANGDB_BASE_URL = "https://api.us-east-1.langdb.ai"
85
86
  OLLAMA_API_KEY = "ollama"
86
87
  DUMMY_API_KEY = "xxx"
87
88
 
89
+ VLLM_API_KEY = os.environ.get("VLLM_API_KEY", DUMMY_API_KEY)
90
+ LLAMACPP_API_KEY = os.environ.get("LLAMA_API_KEY", DUMMY_API_KEY)
91
+
88
92
 
89
93
  openai_chat_model_pref_list = [
90
94
  OpenAIChatModel.GPT4o,
@@ -177,6 +181,24 @@ def noop() -> None:
177
181
  return None
178
182
 
179
183
 
184
+ class LangDBParams(BaseSettings):
185
+ """
186
+ Parameters specific to LangDB integration.
187
+ """
188
+
189
+ api_key: str = DUMMY_API_KEY
190
+ project_id: str = ""
191
+ label: Optional[str] = None
192
+ run_id: Optional[str] = None
193
+ thread_id: Optional[str] = None
194
+ base_url: str = LANGDB_BASE_URL
195
+
196
+ class Config:
197
+ # allow setting of fields via env vars,
198
+ # e.g. LANGDB_PROJECT_ID=1234
199
+ env_prefix = "LANGDB_"
200
+
201
+
180
202
  class OpenAICallParams(BaseModel):
181
203
  """
182
204
  Various params that can be sent to an OpenAI API chat-completion call.
@@ -253,6 +275,8 @@ class OpenAIGPTConfig(LLMConfig):
253
275
  # e.g. "mistral-instruct-v0.2 (a fuzzy search is done to find the closest match)
254
276
  formatter: str | None = None
255
277
  hf_formatter: HFFormatter | None = None
278
+ langdb_params: LangDBParams = LangDBParams()
279
+ headers: Dict[str, str] = {}
256
280
 
257
281
  def __init__(self, **kwargs) -> None: # type: ignore
258
282
  local_model = "api_base" in kwargs and kwargs["api_base"] is not None
@@ -496,6 +520,7 @@ class OpenAIGPT(LanguageModel):
496
520
  self.is_deepseek = self.is_deepseek_model()
497
521
  self.is_glhf = self.config.chat_model.startswith("glhf/")
498
522
  self.is_openrouter = self.config.chat_model.startswith("openrouter/")
523
+ self.is_langdb = self.config.chat_model.startswith("langdb/")
499
524
 
500
525
  if self.is_groq:
501
526
  # use groq-specific client
@@ -544,18 +569,39 @@ class OpenAIGPT(LanguageModel):
544
569
  self.api_base = DEEPSEEK_BASE_URL
545
570
  if self.api_key == OPENAI_API_KEY:
546
571
  self.api_key = os.getenv("DEEPSEEK_API_KEY", DUMMY_API_KEY)
572
+ elif self.is_langdb:
573
+ self.config.chat_model = self.config.chat_model.replace("langdb/", "")
574
+ self.api_base = self.config.langdb_params.base_url
575
+ project_id = self.config.langdb_params.project_id
576
+ if project_id:
577
+ self.api_base += "/" + project_id + "/v1"
578
+ if self.api_key == OPENAI_API_KEY:
579
+ self.api_key = self.config.langdb_params.api_key or DUMMY_API_KEY
580
+
581
+ if self.config.langdb_params:
582
+ params = self.config.langdb_params
583
+ if params.project_id:
584
+ self.config.headers["x-project-id"] = params.project_id
585
+ if params.label:
586
+ self.config.headers["x-label"] = params.label
587
+ if params.run_id:
588
+ self.config.headers["x-run-id"] = params.run_id
589
+ if params.thread_id:
590
+ self.config.headers["x-thread-id"] = params.thread_id
547
591
 
548
592
  self.client = OpenAI(
549
593
  api_key=self.api_key,
550
594
  base_url=self.api_base,
551
595
  organization=self.config.organization,
552
596
  timeout=Timeout(self.config.timeout),
597
+ default_headers=self.config.headers,
553
598
  )
554
599
  self.async_client = AsyncOpenAI(
555
600
  api_key=self.api_key,
556
601
  organization=self.config.organization,
557
602
  base_url=self.api_base,
558
603
  timeout=Timeout(self.config.timeout),
604
+ default_headers=self.config.headers,
559
605
  )
560
606
 
561
607
  self.cache: CacheDB | None = None
@@ -1028,6 +1074,7 @@ class OpenAIGPT(LanguageModel):
1028
1074
  OpenAIResponse object (with choices, usage)
1029
1075
 
1030
1076
  """
1077
+
1031
1078
  completion = ""
1032
1079
  reasoning = ""
1033
1080
  function_args = ""
@@ -1075,7 +1122,9 @@ class OpenAIGPT(LanguageModel):
1075
1122
  )
1076
1123
 
1077
1124
  @staticmethod
1078
- def tool_deltas_to_tools(tools: List[Dict[str, Any]]) -> Tuple[
1125
+ def tool_deltas_to_tools(
1126
+ tools: List[Dict[str, Any]],
1127
+ ) -> Tuple[
1079
1128
  str,
1080
1129
  List[OpenAIToolCall],
1081
1130
  List[Dict[str, Any]],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langroid
3
- Version: 0.45.10
3
+ Version: 0.46.0
4
4
  Summary: Harness LLMs with Multi-Agent Programming
5
5
  Author-email: Prasad Chalasani <pchalasani@gmail.com>
6
6
  License: MIT
@@ -59,7 +59,7 @@ langroid/cachedb/momento_cachedb.py,sha256=YEOJ62hEcV6iIeMr5aGgRYgWQqFYaej9gEDEc
59
59
  langroid/cachedb/redis_cachedb.py,sha256=7kgnbf4b5CKsCrlL97mHWKvdvlLt8zgn7lc528jEpiE,5141
60
60
  langroid/embedding_models/__init__.py,sha256=KyYxR3jDFUCfYjSuCL86qjAmrq6mXXjOT4lFNOKVj6Y,955
61
61
  langroid/embedding_models/base.py,sha256=Ml7oA6PzQm0wZmIYn3fhF7dvZCi-amviWUwOeBegH3A,2562
62
- langroid/embedding_models/models.py,sha256=kYGGG-FkmGxNr0msXM3ANZ2eU-C85iTcoWNo00E9F_4,19151
62
+ langroid/embedding_models/models.py,sha256=iGRrQR7ehDunA_7cPMu3CiHFugYWDkauOsiqHH-bv9s,20725
63
63
  langroid/embedding_models/remote_embeds.py,sha256=6_kjXByVbqhY9cGwl9R83ZcYC2km-nGieNNAo1McHaY,5151
64
64
  langroid/embedding_models/protoc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
65
  langroid/embedding_models/protoc/embeddings.proto,sha256=_O-SgFpTaylQeOTgSpxhEJ7CUw7PeCQQJLaPqpPYKJg,321
@@ -72,7 +72,7 @@ langroid/language_models/base.py,sha256=mDYmFCBCLdq8_Uvws4MiewwEgcOCP8Qb0e5yUXr3
72
72
  langroid/language_models/config.py,sha256=9Q8wk5a7RQr8LGMT_0WkpjY8S4ywK06SalVRjXlfCiI,378
73
73
  langroid/language_models/mock_lm.py,sha256=5BgHKDVRWFbUwDT_PFgTZXz9-k8wJSA2e3PZmyDgQ1k,4022
74
74
  langroid/language_models/model_info.py,sha256=tfBBxL0iUf2mVN6CjcvqflzFUVg2oZqOJZexZ8jHTYA,12216
75
- langroid/language_models/openai_gpt.py,sha256=FMi4rQsdJETof5eSQrxIaBdu-5cOHFg8fFy7Hx7twOQ,77691
75
+ langroid/language_models/openai_gpt.py,sha256=Re4T1my9rhOPI-w4JCluhAZUVUIbW2AZJ3MIJMYjRuk,79633
76
76
  langroid/language_models/utils.py,sha256=L4_CbihDMTGcsg0TOG1Yd5JFEto46--h7CX_14m89sQ,5016
77
77
  langroid/language_models/prompt_formatter/__init__.py,sha256=2-5cdE24XoFDhifOLl8yiscohil1ogbP1ECkYdBlBsk,372
78
78
  langroid/language_models/prompt_formatter/base.py,sha256=eDS1sgRNZVnoajwV_ZIha6cba5Dt8xjgzdRbPITwx3Q,1221
@@ -127,7 +127,7 @@ langroid/vector_store/pineconedb.py,sha256=otxXZNaBKb9f_H75HTaU3lMHiaR2NUp5MqwLZ
127
127
  langroid/vector_store/postgres.py,sha256=wHPtIi2qM4fhO4pMQr95pz1ZCe7dTb2hxl4VYspGZoA,16104
128
128
  langroid/vector_store/qdrantdb.py,sha256=O6dSBoDZ0jzfeVBd7LLvsXu083xs2fxXtPa9gGX3JX4,18443
129
129
  langroid/vector_store/weaviatedb.py,sha256=Yn8pg139gOy3zkaPfoTbMXEEBCiLiYa1MU5d_3UA1K4,11847
130
- langroid-0.45.10.dist-info/METADATA,sha256=wprB9hS3tbbIaV9FvHE7VTrTZq0Xv6b0TLu3YG21k6A,63390
131
- langroid-0.45.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
132
- langroid-0.45.10.dist-info/licenses/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
133
- langroid-0.45.10.dist-info/RECORD,,
130
+ langroid-0.46.0.dist-info/METADATA,sha256=S5uBIAjkQEV4KbQSZ2OH-YMoMfGIJtnulBdaYNouSpw,63389
131
+ langroid-0.46.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
132
+ langroid-0.46.0.dist-info/licenses/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
133
+ langroid-0.46.0.dist-info/RECORD,,