langroid 0.34.1__tar.gz → 0.35.1__tar.gz
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.
- {langroid-0.34.1 → langroid-0.35.1}/PKG-INFO +1 -1
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/chat_agent.py +8 -11
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/chat_document.py +2 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/doc_chat_agent.py +27 -2
- {langroid-0.34.1 → langroid-0.35.1}/langroid/language_models/base.py +3 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/language_models/openai_gpt.py +62 -7
- {langroid-0.34.1 → langroid-0.35.1}/langroid/utils/constants.py +2 -0
- {langroid-0.34.1 → langroid-0.35.1}/pyproject.toml +2 -2
- {langroid-0.34.1 → langroid-0.35.1}/.gitignore +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/LICENSE +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/README.md +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/base.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/batch.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/callbacks/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/callbacks/chainlit.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/openai_assistant.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/arangodb/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/arangodb/arangodb_agent.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/arangodb/system_messages.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/arangodb/tools.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/arangodb/utils.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/lance_doc_chat_agent.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/lance_rag/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/lance_rag/critic_agent.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/lance_rag/lance_rag_task.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/lance_rag/query_planner_agent.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/lance_tools.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/neo4j/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/neo4j/csv_kg_chat.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/neo4j/neo4j_chat_agent.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/neo4j/system_messages.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/neo4j/tools.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/relevance_extractor_agent.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/retriever_agent.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/sql/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/sql/sql_chat_agent.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/sql/utils/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/sql/utils/description_extractors.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/sql/utils/populate_metadata.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/sql/utils/system_message.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/sql/utils/tools.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/table_chat_agent.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/task.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/tool_message.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/tools/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/tools/duckduckgo_search_tool.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/tools/file_tools.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/tools/google_search_tool.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/tools/metaphor_search_tool.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/tools/orchestration.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/tools/recipient_tool.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/tools/retrieval_tool.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/tools/rewind_tool.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/tools/segment_extract_tool.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/agent/xml_tool_message.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/cachedb/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/cachedb/base.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/cachedb/momento_cachedb.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/cachedb/redis_cachedb.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/embedding_models/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/embedding_models/base.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/embedding_models/models.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/embedding_models/protoc/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/embedding_models/protoc/embeddings.proto +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/embedding_models/protoc/embeddings_pb2.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/embedding_models/protoc/embeddings_pb2.pyi +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/embedding_models/protoc/embeddings_pb2_grpc.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/embedding_models/remote_embeds.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/exceptions.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/language_models/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/language_models/azure_openai.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/language_models/config.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/language_models/mock_lm.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/language_models/prompt_formatter/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/language_models/prompt_formatter/base.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/language_models/prompt_formatter/hf_formatter.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/language_models/prompt_formatter/llama2_formatter.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/language_models/utils.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/mytypes.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/parsing/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/parsing/agent_chats.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/parsing/code_parser.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/parsing/document_parser.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/parsing/para_sentence_split.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/parsing/parse_json.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/parsing/parser.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/parsing/repo_loader.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/parsing/routing.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/parsing/search.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/parsing/spider.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/parsing/table_loader.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/parsing/url_loader.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/parsing/urls.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/parsing/utils.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/parsing/web_search.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/prompts/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/prompts/dialog.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/prompts/prompts_config.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/prompts/templates.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/py.typed +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/pydantic_v1/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/pydantic_v1/main.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/utils/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/utils/algorithms/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/utils/algorithms/graph.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/utils/configuration.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/utils/git_utils.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/utils/globals.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/utils/logging.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/utils/object_registry.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/utils/output/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/utils/output/citations.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/utils/output/printing.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/utils/output/status.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/utils/pandas_utils.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/utils/pydantic_utils.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/utils/system.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/utils/types.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/vector_store/__init__.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/vector_store/base.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/vector_store/chromadb.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/vector_store/lancedb.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/vector_store/meilisearch.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/vector_store/momento.py +0 -0
- {langroid-0.34.1 → langroid-0.35.1}/langroid/vector_store/qdrantdb.py +0 -0
@@ -416,7 +416,7 @@ class ChatAgent(Agent):
|
|
416
416
|
]
|
417
417
|
|
418
418
|
if len(usable_tool_classes) == 0:
|
419
|
-
return "
|
419
|
+
return ""
|
420
420
|
format_instructions = "\n\n".join(
|
421
421
|
[
|
422
422
|
msg_cls.format_instructions(tool=self.config.use_tools)
|
@@ -568,17 +568,14 @@ class ChatAgent(Agent):
|
|
568
568
|
Returns:
|
569
569
|
LLMMessage object
|
570
570
|
"""
|
571
|
-
content =
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
571
|
+
content = self.system_message
|
572
|
+
if self.system_tool_instructions != "":
|
573
|
+
content += "\n\n" + self.system_tool_instructions
|
574
|
+
if self.system_tool_format_instructions != "":
|
575
|
+
content += "\n\n" + self.system_tool_format_instructions
|
576
|
+
if self.output_format_instructions != "":
|
577
|
+
content += "\n\n" + self.output_format_instructions
|
578
578
|
|
579
|
-
{self.output_format_instructions}
|
580
|
-
"""
|
581
|
-
)
|
582
579
|
# remove leading and trailing newlines and other whitespace
|
583
580
|
return LLMMessage(role=Role.SYSTEM, content=content.strip())
|
584
581
|
|
@@ -117,6 +117,7 @@ class ChatDocument(Document):
|
|
117
117
|
attachment (None | ChatDocAttachment): Any additional data attached.
|
118
118
|
"""
|
119
119
|
|
120
|
+
reasoning: str = "" # reasoning produced by a reasoning LLM
|
120
121
|
content_any: Any = None # to hold arbitrary data returned by responders
|
121
122
|
oai_tool_calls: Optional[List[OpenAIToolCall]] = None
|
122
123
|
oai_tool_id2result: Optional[OrderedDict[str, str]] = None
|
@@ -297,6 +298,7 @@ class ChatDocument(Document):
|
|
297
298
|
ChatDocument._clean_fn_call(oai_tc.function)
|
298
299
|
return ChatDocument(
|
299
300
|
content=message,
|
301
|
+
reasoning=response.reasoning,
|
300
302
|
content_any=message,
|
301
303
|
oai_tool_calls=response.oai_tool_calls,
|
302
304
|
function_call=response.function_call,
|
@@ -212,6 +212,12 @@ class DocChatAgentConfig(ChatAgentConfig):
|
|
212
212
|
)
|
213
213
|
|
214
214
|
|
215
|
+
def _append_metadata_source(orig_source: str, source: str) -> str:
|
216
|
+
if orig_source != source and source != "" and orig_source != "":
|
217
|
+
return f"{orig_source.strip()}; {source.strip()}"
|
218
|
+
return orig_source.strip() + source.strip()
|
219
|
+
|
220
|
+
|
215
221
|
class DocChatAgent(ChatAgent):
|
216
222
|
"""
|
217
223
|
Agent for chatting with a collection of documents.
|
@@ -337,7 +343,11 @@ class DocChatAgent(ChatAgent):
|
|
337
343
|
url_docs = loader.load()
|
338
344
|
# update metadata of each doc with meta
|
339
345
|
for d in url_docs:
|
346
|
+
orig_source = d.metadata.source
|
340
347
|
d.metadata = d.metadata.copy(update=meta)
|
348
|
+
d.metadata.source = _append_metadata_source(
|
349
|
+
orig_source, meta.get("source", "")
|
350
|
+
)
|
341
351
|
docs.extend(url_docs)
|
342
352
|
if len(paths) > 0: # paths OR bytes are handled similarly
|
343
353
|
for pi in path_idxs:
|
@@ -350,7 +360,11 @@ class DocChatAgent(ChatAgent):
|
|
350
360
|
)
|
351
361
|
# update metadata of each doc with meta
|
352
362
|
for d in path_docs:
|
363
|
+
orig_source = d.metadata.source
|
353
364
|
d.metadata = d.metadata.copy(update=meta)
|
365
|
+
d.metadata.source = _append_metadata_source(
|
366
|
+
orig_source, meta.get("source", "")
|
367
|
+
)
|
354
368
|
docs.extend(path_docs)
|
355
369
|
n_docs = len(docs)
|
356
370
|
n_splits = self.ingest_docs(docs, split=self.config.split)
|
@@ -391,15 +405,26 @@ class DocChatAgent(ChatAgent):
|
|
391
405
|
"""
|
392
406
|
if isinstance(metadata, list) and len(metadata) > 0:
|
393
407
|
for d, m in zip(docs, metadata):
|
394
|
-
|
395
|
-
|
408
|
+
orig_source = d.metadata.source
|
409
|
+
m_dict = m if isinstance(m, dict) else m.dict() # type: ignore
|
410
|
+
d.metadata = d.metadata.copy(update=m_dict) # type: ignore
|
411
|
+
d.metadata.source = _append_metadata_source(
|
412
|
+
orig_source, m_dict.get("source", "")
|
396
413
|
)
|
397
414
|
elif isinstance(metadata, dict):
|
398
415
|
for d in docs:
|
416
|
+
orig_source = d.metadata.source
|
399
417
|
d.metadata = d.metadata.copy(update=metadata)
|
418
|
+
d.metadata.source = _append_metadata_source(
|
419
|
+
orig_source, metadata.get("source", "")
|
420
|
+
)
|
400
421
|
elif isinstance(metadata, DocMetaData):
|
401
422
|
for d in docs:
|
423
|
+
orig_source = d.metadata.source
|
402
424
|
d.metadata = d.metadata.copy(update=metadata.dict())
|
425
|
+
d.metadata.source = _append_metadata_source(
|
426
|
+
orig_source, metadata.source
|
427
|
+
)
|
403
428
|
|
404
429
|
self.original_docs.extend(docs)
|
405
430
|
if self.parser is None:
|
@@ -75,6 +75,8 @@ class LLMConfig(BaseSettings):
|
|
75
75
|
# use chat model for completion? For OpenAI models, this MUST be set to True!
|
76
76
|
use_chat_for_completion: bool = True
|
77
77
|
stream: bool = True # stream output from API?
|
78
|
+
# TODO: we could have a `stream_reasoning` flag here to control whether to show
|
79
|
+
# reasoning output from reasoning models
|
78
80
|
cache_config: None | CacheDBConfig = RedisCacheConfig()
|
79
81
|
|
80
82
|
# Dict of model -> (input/prompt cost, output/completion cost)
|
@@ -317,6 +319,7 @@ class LLMResponse(BaseModel):
|
|
317
319
|
"""
|
318
320
|
|
319
321
|
message: str
|
322
|
+
reasoning: str = "" # optional reasoning text from reasoning models
|
320
323
|
# TODO tool_id needs to generalize to multi-tool calls
|
321
324
|
tool_id: str = "" # used by OpenAIAssistant
|
322
325
|
oai_tool_calls: Optional[List[OpenAIToolCall]] = None
|
@@ -820,6 +820,7 @@ class OpenAIGPT(LanguageModel):
|
|
820
820
|
tool_deltas: List[Dict[str, Any]] = [],
|
821
821
|
has_function: bool = False,
|
822
822
|
completion: str = "",
|
823
|
+
reasoning: str = "",
|
823
824
|
function_args: str = "",
|
824
825
|
function_name: str = "",
|
825
826
|
) -> Tuple[bool, bool, str, str]:
|
@@ -845,7 +846,9 @@ class OpenAIGPT(LanguageModel):
|
|
845
846
|
# In the 1st: choices list is empty, in the 2nd: the dict delta has null content
|
846
847
|
if chat:
|
847
848
|
delta = choices[0].get("delta", {})
|
849
|
+
# capture both content and reasoning_content
|
848
850
|
event_text = delta.get("content", "")
|
851
|
+
event_reasoning = delta.get("reasoning_content", "")
|
849
852
|
if "function_call" in delta and delta["function_call"] is not None:
|
850
853
|
if "name" in delta["function_call"]:
|
851
854
|
event_fn_name = delta["function_call"]["name"]
|
@@ -857,6 +860,7 @@ class OpenAIGPT(LanguageModel):
|
|
857
860
|
tool_deltas += event_tool_deltas
|
858
861
|
else:
|
859
862
|
event_text = choices[0]["text"]
|
863
|
+
event_reasoning = "" # TODO: Ignoring reasoning for non-chat models
|
860
864
|
|
861
865
|
finish_reason = choices[0].get("finish_reason", "")
|
862
866
|
if not event_text and finish_reason == "content_filter":
|
@@ -877,6 +881,11 @@ class OpenAIGPT(LanguageModel):
|
|
877
881
|
sys.stdout.write(Colors().GREEN + event_text)
|
878
882
|
sys.stdout.flush()
|
879
883
|
self.config.streamer(event_text, StreamEventType.TEXT)
|
884
|
+
if event_reasoning:
|
885
|
+
reasoning += event_reasoning
|
886
|
+
sys.stdout.write(Colors().GREEN_DIM + event_reasoning)
|
887
|
+
sys.stdout.flush()
|
888
|
+
self.config.streamer(event_reasoning, StreamEventType.TEXT)
|
880
889
|
if event_fn_name:
|
881
890
|
function_name = event_fn_name
|
882
891
|
has_function = True
|
@@ -915,8 +924,15 @@ class OpenAIGPT(LanguageModel):
|
|
915
924
|
# for function_call, finish_reason does not necessarily
|
916
925
|
# contain "function_call" as mentioned in the docs.
|
917
926
|
# So we check for "stop" or "function_call" here.
|
918
|
-
return
|
919
|
-
|
927
|
+
return (
|
928
|
+
True,
|
929
|
+
has_function,
|
930
|
+
function_name,
|
931
|
+
function_args,
|
932
|
+
completion,
|
933
|
+
reasoning,
|
934
|
+
)
|
935
|
+
return False, has_function, function_name, function_args, completion, reasoning
|
920
936
|
|
921
937
|
@no_type_check
|
922
938
|
async def _process_stream_event_async(
|
@@ -926,6 +942,7 @@ class OpenAIGPT(LanguageModel):
|
|
926
942
|
tool_deltas: List[Dict[str, Any]] = [],
|
927
943
|
has_function: bool = False,
|
928
944
|
completion: str = "",
|
945
|
+
reasoning: str = "",
|
929
946
|
function_args: str = "",
|
930
947
|
function_name: str = "",
|
931
948
|
) -> Tuple[bool, bool, str, str]:
|
@@ -953,6 +970,7 @@ class OpenAIGPT(LanguageModel):
|
|
953
970
|
if chat:
|
954
971
|
delta = choices[0].get("delta", {})
|
955
972
|
event_text = delta.get("content", "")
|
973
|
+
event_reasoning = delta.get("reasoning_content", "")
|
956
974
|
if "function_call" in delta and delta["function_call"] is not None:
|
957
975
|
if "name" in delta["function_call"]:
|
958
976
|
event_fn_name = delta["function_call"]["name"]
|
@@ -964,12 +982,19 @@ class OpenAIGPT(LanguageModel):
|
|
964
982
|
tool_deltas += event_tool_deltas
|
965
983
|
else:
|
966
984
|
event_text = choices[0]["text"]
|
985
|
+
event_reasoning = "" # TODO: Ignoring reasoning for non-chat models
|
967
986
|
if event_text:
|
968
987
|
completion += event_text
|
969
988
|
if not silent:
|
970
989
|
sys.stdout.write(Colors().GREEN + event_text)
|
971
990
|
sys.stdout.flush()
|
972
991
|
await self.config.streamer_async(event_text, StreamEventType.TEXT)
|
992
|
+
if event_reasoning:
|
993
|
+
reasoning += event_reasoning
|
994
|
+
if not silent:
|
995
|
+
sys.stdout.write(Colors().GREEN + event_reasoning)
|
996
|
+
sys.stdout.flush()
|
997
|
+
await self.config.streamer_async(event_reasoning, StreamEventType.TEXT)
|
973
998
|
if event_fn_name:
|
974
999
|
function_name = event_fn_name
|
975
1000
|
has_function = True
|
@@ -1016,8 +1041,15 @@ class OpenAIGPT(LanguageModel):
|
|
1016
1041
|
# for function_call, finish_reason does not necessarily
|
1017
1042
|
# contain "function_call" as mentioned in the docs.
|
1018
1043
|
# So we check for "stop" or "function_call" here.
|
1019
|
-
return
|
1020
|
-
|
1044
|
+
return (
|
1045
|
+
True,
|
1046
|
+
has_function,
|
1047
|
+
function_name,
|
1048
|
+
function_args,
|
1049
|
+
completion,
|
1050
|
+
reasoning,
|
1051
|
+
)
|
1052
|
+
return False, has_function, function_name, function_args, completion, reasoning
|
1021
1053
|
|
1022
1054
|
@retry_with_exponential_backoff
|
1023
1055
|
def _stream_response( # type: ignore
|
@@ -1035,6 +1067,7 @@ class OpenAIGPT(LanguageModel):
|
|
1035
1067
|
|
1036
1068
|
"""
|
1037
1069
|
completion = ""
|
1070
|
+
reasoning = ""
|
1038
1071
|
function_args = ""
|
1039
1072
|
function_name = ""
|
1040
1073
|
|
@@ -1050,12 +1083,14 @@ class OpenAIGPT(LanguageModel):
|
|
1050
1083
|
function_name,
|
1051
1084
|
function_args,
|
1052
1085
|
completion,
|
1086
|
+
reasoning,
|
1053
1087
|
) = self._process_stream_event(
|
1054
1088
|
event,
|
1055
1089
|
chat=chat,
|
1056
1090
|
tool_deltas=tool_deltas,
|
1057
1091
|
has_function=has_function,
|
1058
1092
|
completion=completion,
|
1093
|
+
reasoning=reasoning,
|
1059
1094
|
function_args=function_args,
|
1060
1095
|
function_name=function_name,
|
1061
1096
|
)
|
@@ -1072,6 +1107,7 @@ class OpenAIGPT(LanguageModel):
|
|
1072
1107
|
tool_deltas=tool_deltas,
|
1073
1108
|
has_function=has_function,
|
1074
1109
|
completion=completion,
|
1110
|
+
reasoning=reasoning,
|
1075
1111
|
function_args=function_args,
|
1076
1112
|
function_name=function_name,
|
1077
1113
|
)
|
@@ -1092,6 +1128,7 @@ class OpenAIGPT(LanguageModel):
|
|
1092
1128
|
|
1093
1129
|
"""
|
1094
1130
|
completion = ""
|
1131
|
+
reasoning = ""
|
1095
1132
|
function_args = ""
|
1096
1133
|
function_name = ""
|
1097
1134
|
|
@@ -1107,12 +1144,14 @@ class OpenAIGPT(LanguageModel):
|
|
1107
1144
|
function_name,
|
1108
1145
|
function_args,
|
1109
1146
|
completion,
|
1147
|
+
reasoning,
|
1110
1148
|
) = await self._process_stream_event_async(
|
1111
1149
|
event,
|
1112
1150
|
chat=chat,
|
1113
1151
|
tool_deltas=tool_deltas,
|
1114
1152
|
has_function=has_function,
|
1115
1153
|
completion=completion,
|
1154
|
+
reasoning=reasoning,
|
1116
1155
|
function_args=function_args,
|
1117
1156
|
function_name=function_name,
|
1118
1157
|
)
|
@@ -1129,6 +1168,7 @@ class OpenAIGPT(LanguageModel):
|
|
1129
1168
|
tool_deltas=tool_deltas,
|
1130
1169
|
has_function=has_function,
|
1131
1170
|
completion=completion,
|
1171
|
+
reasoning=reasoning,
|
1132
1172
|
function_args=function_args,
|
1133
1173
|
function_name=function_name,
|
1134
1174
|
)
|
@@ -1263,6 +1303,7 @@ class OpenAIGPT(LanguageModel):
|
|
1263
1303
|
tool_deltas: List[Dict[str, Any]] = [],
|
1264
1304
|
has_function: bool = False,
|
1265
1305
|
completion: str = "",
|
1306
|
+
reasoning: str = "",
|
1266
1307
|
function_args: str = "",
|
1267
1308
|
function_name: str = "",
|
1268
1309
|
) -> Tuple[LLMResponse, Dict[str, Any]]:
|
@@ -1298,7 +1339,12 @@ class OpenAIGPT(LanguageModel):
|
|
1298
1339
|
tool_deltas,
|
1299
1340
|
)
|
1300
1341
|
completion = completion + "\n" + failed_content
|
1301
|
-
msg: Dict[str, Any] = dict(
|
1342
|
+
msg: Dict[str, Any] = dict(
|
1343
|
+
message=dict(
|
1344
|
+
content=completion,
|
1345
|
+
reasoning_content=reasoning,
|
1346
|
+
),
|
1347
|
+
)
|
1302
1348
|
if len(tool_dicts) > 0:
|
1303
1349
|
msg["message"]["tool_calls"] = tool_dicts
|
1304
1350
|
|
@@ -1314,6 +1360,7 @@ class OpenAIGPT(LanguageModel):
|
|
1314
1360
|
else:
|
1315
1361
|
# non-chat mode has no function_call
|
1316
1362
|
msg = dict(text=completion)
|
1363
|
+
# TODO: Ignoring reasoning content for non-chat models
|
1317
1364
|
|
1318
1365
|
# create an OpenAIResponse object so we can cache it as if it were
|
1319
1366
|
# a non-streaming response
|
@@ -1324,6 +1371,7 @@ class OpenAIGPT(LanguageModel):
|
|
1324
1371
|
return (
|
1325
1372
|
LLMResponse(
|
1326
1373
|
message=completion,
|
1374
|
+
reasoning=reasoning,
|
1327
1375
|
cached=False,
|
1328
1376
|
# don't allow empty list [] here
|
1329
1377
|
oai_tool_calls=tool_calls or None if len(tool_deltas) > 0 else None,
|
@@ -1461,6 +1509,7 @@ class OpenAIGPT(LanguageModel):
|
|
1461
1509
|
)
|
1462
1510
|
args = self._openai_api_call_params(args)
|
1463
1511
|
cached, hashed_key, response = completions_with_backoff(**args)
|
1512
|
+
# assume response is an actual response rather than a streaming event
|
1464
1513
|
if not isinstance(response, dict):
|
1465
1514
|
response = response.dict()
|
1466
1515
|
if "message" in response["choices"][0]:
|
@@ -1534,6 +1583,7 @@ class OpenAIGPT(LanguageModel):
|
|
1534
1583
|
max_tokens=max_tokens,
|
1535
1584
|
stream=False,
|
1536
1585
|
)
|
1586
|
+
# assume response is an actual response rather than a streaming event
|
1537
1587
|
if not isinstance(response, dict):
|
1538
1588
|
response = response.dict()
|
1539
1589
|
if "message" in response["choices"][0]:
|
@@ -1738,7 +1788,9 @@ class OpenAIGPT(LanguageModel):
|
|
1738
1788
|
if (
|
1739
1789
|
len(llm_messages) == 1
|
1740
1790
|
and llm_messages[0].role == Role.SYSTEM
|
1741
|
-
|
1791
|
+
# TODO: we will unconditionally insert a dummy user msg
|
1792
|
+
# if the only msg is a system msg.
|
1793
|
+
# and self.requires_first_user_message()
|
1742
1794
|
):
|
1743
1795
|
# some LLMs, notable Gemini as of 12/11/24,
|
1744
1796
|
# require the first message to be from the user,
|
@@ -1827,6 +1879,7 @@ class OpenAIGPT(LanguageModel):
|
|
1827
1879
|
"role": "assistant",
|
1828
1880
|
"name": "",
|
1829
1881
|
"content": "\n\nHello there, how may I help you?",
|
1882
|
+
"reasoning_content": "Okay, let's see here, hmmm...",
|
1830
1883
|
"function_call": {
|
1831
1884
|
"name": "fun_name",
|
1832
1885
|
"arguments: {
|
@@ -1845,7 +1898,8 @@ class OpenAIGPT(LanguageModel):
|
|
1845
1898
|
}
|
1846
1899
|
"""
|
1847
1900
|
message = response["choices"][0]["message"]
|
1848
|
-
msg = message
|
1901
|
+
msg = message.get("content", "")
|
1902
|
+
reasoning = message.get("reasoning_content", "")
|
1849
1903
|
|
1850
1904
|
if message.get("function_call") is None:
|
1851
1905
|
fun_call = None
|
@@ -1879,6 +1933,7 @@ class OpenAIGPT(LanguageModel):
|
|
1879
1933
|
msg = msg + "\n" + json.dumps(tool_call_dict)
|
1880
1934
|
return LLMResponse(
|
1881
1935
|
message=msg.strip() if msg is not None else "",
|
1936
|
+
reasoning=reasoning.strip() if reasoning is not None else "",
|
1882
1937
|
function_call=fun_call,
|
1883
1938
|
oai_tool_calls=oai_tool_calls or None, # don't allow empty list [] here
|
1884
1939
|
cached=cached,
|
@@ -6,6 +6,8 @@ class Colors(BaseModel):
|
|
6
6
|
RED: str = "\033[31m"
|
7
7
|
BLUE: str = "\033[34m"
|
8
8
|
GREEN: str = "\033[32m"
|
9
|
+
GREEN_DIMMER: str = "\033[38;5;22m" # very dark green
|
10
|
+
GREEN_DIM: str = "\033[38;5;28m" # medium-dim green
|
9
11
|
ORANGE: str = "\033[33m" # no standard ANSI color for orange; using yellow
|
10
12
|
CYAN: str = "\033[36m"
|
11
13
|
MAGENTA: str = "\033[35m"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "langroid"
|
3
|
-
version = "0.
|
3
|
+
version = "0.35.1"
|
4
4
|
authors = [
|
5
5
|
{name = "Prasad Chalasani", email = "pchalasani@gmail.com"},
|
6
6
|
]
|
@@ -220,13 +220,13 @@ dev = [
|
|
220
220
|
"pytest-redis<4.0.0,>=3.0.2",
|
221
221
|
"pytest-asyncio<1.0.0,>=0.21.1",
|
222
222
|
"pytest-postgresql<6.0.0,>=5.0.0",
|
223
|
-
"pytest-mysql<3.0.0,>=2.4.2",
|
224
223
|
"coverage<8.0.0,>=7.2.5",
|
225
224
|
"pytest-xdist<4.0.0,>=3.6.1",
|
226
225
|
"pytest-timeout<3.0.0,>=2.3.1",
|
227
226
|
"pytest-cov<6.0.0,>=5.0.0",
|
228
227
|
"docker<8.0.0,>=7.1.0",
|
229
228
|
"commitizen>=4.1.0",
|
229
|
+
"pytest-mysql>=3.1.0",
|
230
230
|
]
|
231
231
|
docs = [
|
232
232
|
"mkdocs<2.0.0,>=1.4.2",
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{langroid-0.34.1 → langroid-0.35.1}/langroid/agent/special/sql/utils/description_extractors.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{langroid-0.34.1 → langroid-0.35.1}/langroid/language_models/prompt_formatter/hf_formatter.py
RENAMED
File without changes
|
{langroid-0.34.1 → langroid-0.35.1}/langroid/language_models/prompt_formatter/llama2_formatter.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|