lollms-client 0.29.0__tar.gz → 0.29.2__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.
Potentially problematic release.
This version of lollms-client might be problematic. Click here for more details.
- {lollms_client-0.29.0/lollms_client.egg-info → lollms_client-0.29.2}/PKG-INFO +300 -47
- {lollms_client-0.29.0 → lollms_client-0.29.2}/README.md +299 -46
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/text_gen.py +1 -1
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/__init__.py +1 -1
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/llm_bindings/llamacpp/__init__.py +6 -2
- {lollms_client-0.29.0/lollms_client/llm_bindings/lollms_chat → lollms_client-0.29.2/lollms_client/llm_bindings/lollms}/__init__.py +8 -7
- {lollms_client-0.29.0/lollms_client/llm_bindings/lollms → lollms_client-0.29.2/lollms_client/llm_bindings/lollms_webui}/__init__.py +2 -2
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/lollms_core.py +151 -124
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/lollms_discussion.py +261 -41
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/lollms_utilities.py +10 -2
- {lollms_client-0.29.0 → lollms_client-0.29.2/lollms_client.egg-info}/PKG-INFO +300 -47
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client.egg-info/SOURCES.txt +1 -1
- {lollms_client-0.29.0 → lollms_client-0.29.2}/LICENSE +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/article_summary/article_summary.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/console_discussion/console_app.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/console_discussion.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/deep_analyze/deep_analyse.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/deep_analyze/deep_analyze_multiple_files.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/function_calling_with_local_custom_mcp.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/generate_a_benchmark_for_safe_store.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/generate_and_speak/generate_and_speak.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/generate_game_sfx/generate_game_fx.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/generate_text_with_multihop_rag_example.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/gradio_chat_app.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/gradio_lollms_chat.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/internet_search_with_rag.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/lollms_chat/calculator.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/lollms_chat/derivative.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/lollms_chat/test_openai_compatible_with_lollms_chat.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/lollms_discussions_test.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/mcp_examples/external_mcp.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/mcp_examples/local_mcp.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/mcp_examples/openai_mcp.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/mcp_examples/run_remote_mcp_example_v2.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/mcp_examples/run_standard_mcp_example.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/simple_text_gen_test.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/simple_text_gen_with_image_test.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/test_local_models/local_chat.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/text_2_audio.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/text_2_image.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/text_2_image_diffusers.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/text_and_image_2_audio.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/examples/text_gen_system_prompt.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/llm_bindings/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/llm_bindings/azure_openai/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/llm_bindings/claude/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/llm_bindings/gemini/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/llm_bindings/grok/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/llm_bindings/groq/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/llm_bindings/hugging_face_inference_api/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/llm_bindings/litellm/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/llm_bindings/mistral/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/llm_bindings/ollama/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/llm_bindings/open_router/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/llm_bindings/openai/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/llm_bindings/openllm/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/llm_bindings/pythonllamacpp/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/llm_bindings/tensor_rt/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/llm_bindings/transformers/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/llm_bindings/vllm/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/lollms_config.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/lollms_js_analyzer.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/lollms_llm_binding.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/lollms_mcp_binding.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/lollms_personality.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/lollms_python_analyzer.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/lollms_stt_binding.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/lollms_tti_binding.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/lollms_ttm_binding.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/lollms_tts_binding.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/lollms_ttv_binding.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/lollms_types.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/mcp_bindings/local_mcp/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/mcp_bindings/local_mcp/default_tools/file_writer/file_writer.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/mcp_bindings/local_mcp/default_tools/generate_image_from_prompt/generate_image_from_prompt.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/mcp_bindings/local_mcp/default_tools/internet_search/internet_search.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/mcp_bindings/local_mcp/default_tools/python_interpreter/python_interpreter.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/mcp_bindings/remote_mcp/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/mcp_bindings/standard_mcp/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/stt_bindings/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/stt_bindings/lollms/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/stt_bindings/whisper/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/stt_bindings/whispercpp/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/tti_bindings/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/tti_bindings/dalle/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/tti_bindings/diffusers/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/tti_bindings/gemini/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/tti_bindings/lollms/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/ttm_bindings/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/ttm_bindings/audiocraft/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/ttm_bindings/bark/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/ttm_bindings/lollms/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/tts_bindings/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/tts_bindings/bark/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/tts_bindings/lollms/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/tts_bindings/piper_tts/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/tts_bindings/xtts/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/ttv_bindings/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client/ttv_bindings/lollms/__init__.py +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client.egg-info/dependency_links.txt +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client.egg-info/requires.txt +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/lollms_client.egg-info/top_level.txt +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/pyproject.toml +0 -0
- {lollms_client-0.29.0 → lollms_client-0.29.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lollms_client
|
|
3
|
-
Version: 0.29.
|
|
3
|
+
Version: 0.29.2
|
|
4
4
|
Summary: A client library for LoLLMs generate endpoint
|
|
5
5
|
Author-email: ParisNeo <parisneoai@gmail.com>
|
|
6
6
|
License: Apache Software License
|
|
@@ -51,8 +51,12 @@ Whether you're connecting to a remote LoLLMs server, an Ollama instance, the Ope
|
|
|
51
51
|
* 🤖 **Function Calling with MCP:** Empowers LLMs to use external tools and functions through the Model Context Protocol (MCP), with built-in support for local Python tool execution via `local_mcp` binding and its default tools (file I/O, internet search, Python interpreter, image generation).
|
|
52
52
|
* 🎭 **Personalities as Agents:** Personalities can now define their own set of required tools (MCPs) and have access to static or dynamic knowledge bases (`data_source`), turning them into self-contained, ready-to-use agents.
|
|
53
53
|
* 🚀 **Streaming & Callbacks:** Efficiently handle real-time text generation with customizable callback functions, including during MCP interactions.
|
|
54
|
+
* 📑 **Sequential Summarization:** A `summarize` method to process and summarize texts that exceed the model's context window.
|
|
54
55
|
* 📝 **Advanced Structured Content Generation:** Reliably generate structured JSON output from natural language prompts using the `generate_structured_content` helper method.
|
|
55
|
-
* 💬 **Discussion Management:**
|
|
56
|
+
* 💬 **Advanced Discussion Management:** Robustly manage conversation histories with `LollmsDiscussion`, featuring branching, context exporting, and automatic pruning.
|
|
57
|
+
* 🧠 **Persistent Memory & Data Zones:** `LollmsDiscussion` now supports multiple, distinct data zones (`user_data_zone`, `discussion_data_zone`, `personality_data_zone`) and a long-term `memory` field. This allows for sophisticated context layering and state management.
|
|
58
|
+
* ✍️ **Automatic Memorization:** A new `memorize()` method allows the AI to analyze a conversation and extract key facts, appending them to the long-term `memory` for recall in future sessions.
|
|
59
|
+
* 📊 **Detailed Context Analysis:** The `get_context_status()` method now provides a rich, detailed breakdown of the prompt context, showing the content and token count for each individual component (system prompt, data zones, message history).
|
|
56
60
|
* ⚙️ **Configuration Management:** Flexible ways to configure bindings and generation parameters.
|
|
57
61
|
* 🧩 **Extensible:** Designed to easily incorporate new LLM backends and modality services, including custom MCP toolsets.
|
|
58
62
|
* 📝 **High-Level Operations:** Includes convenience methods for complex tasks like sequential summarization and deep text analysis directly within `LollmsClient`.
|
|
@@ -185,7 +189,7 @@ This script will define the personality, initialize the client, and run the agen
|
|
|
185
189
|
|
|
186
190
|
```python
|
|
187
191
|
from pathlib import Path
|
|
188
|
-
from lollms_client import LollmsClient, LollmsPersonality, LollmsDiscussion, MSG_TYPE
|
|
192
|
+
from lollms_client import LollmsClient, LollmsPersonality, LollmsDiscussion, MSG_TYPE, trace_exception
|
|
189
193
|
from ascii_colors import ASCIIColors
|
|
190
194
|
import json
|
|
191
195
|
|
|
@@ -276,11 +280,11 @@ except Exception as e:
|
|
|
276
280
|
When you run `agent_example.py`, a sophisticated process unfolds:
|
|
277
281
|
|
|
278
282
|
1. **Initialization:** The `LollmsDiscussion.chat()` method is called with the `coder_personality`.
|
|
279
|
-
2. **Knowledge Injection:** The `chat` method sees that `personality.data_source` is a string. It automatically takes the content of `coding_rules.txt` and injects it into the
|
|
283
|
+
2. **Knowledge Injection:** The `chat` method sees that `personality.data_source` is a string. It automatically takes the content of `coding_rules.txt` and injects it into the discussion's data zones.
|
|
280
284
|
3. **Tool Activation:** The method also sees `personality.active_mcps`. It enables the `python_code_interpreter` tool for this turn.
|
|
281
285
|
4. **Context Assembly:** The `LollmsClient` assembles a rich prompt for the LLM that includes:
|
|
282
286
|
* The personality's `system_prompt`.
|
|
283
|
-
* The content of `coding_rules.txt` (from the
|
|
287
|
+
* The content of `coding_rules.txt` (from the data zones).
|
|
284
288
|
* The list of available tools (including `python_code_interpreter`).
|
|
285
289
|
* The user's request ("Write a function...").
|
|
286
290
|
5. **Reason and Act:** The LLM, now fully briefed, reasons that it needs to use the `python_code_interpreter` tool. It formulates the Python code *according to the rules it was given*.
|
|
@@ -290,6 +294,121 @@ When you run `agent_example.py`, a sophisticated process unfolds:
|
|
|
290
294
|
|
|
291
295
|
This example showcases how `lollms-client` allows you to build powerful, knowledgeable, and capable agents by simply composing personalities with data and tools.
|
|
292
296
|
|
|
297
|
+
### Building Stateful Agents with Memory and Data Zones
|
|
298
|
+
|
|
299
|
+
The `LollmsDiscussion` class provides a sophisticated system for creating stateful agents that can remember information across conversations. This is achieved through a layered system of "context zones" that are automatically combined into the AI's system prompt.
|
|
300
|
+
|
|
301
|
+
#### Understanding the Context Zones
|
|
302
|
+
|
|
303
|
+
The AI's context is more than just chat history. It's built from several distinct components, each with a specific purpose:
|
|
304
|
+
|
|
305
|
+
* **`system_prompt`**: The foundational layer defining the AI's core identity, persona, and primary instructions.
|
|
306
|
+
* **`memory`**: The AI's long-term, persistent memory. It stores key facts about the user or topics, built up over time using the `memorize()` method.
|
|
307
|
+
* **`user_data_zone`**: Holds session-specific information about the user's current state or goals (e.g., "User is currently working on 'file.py'").
|
|
308
|
+
* **`discussion_data_zone`**: Contains state or meta-information about the current conversational task (e.g., "Step 1 of the plan is complete").
|
|
309
|
+
* **`personality_data_zone`**: A knowledge base or set of rules automatically injected from a `LollmsPersonality`'s `data_source`.
|
|
310
|
+
* **`pruning_summary`**: An automatic, AI-generated summary of the oldest messages in a very long chat, used to conserve tokens without losing the gist of the early conversation.
|
|
311
|
+
|
|
312
|
+
The `get_context_status()` method is your window into this system, showing you exactly how these zones are combined and how many tokens they consume.
|
|
313
|
+
|
|
314
|
+
Let's see this in action with a "Personal Assistant" agent that learns about the user over time.
|
|
315
|
+
|
|
316
|
+
```python
|
|
317
|
+
from lollms_client import LollmsClient, LollmsDataManager, LollmsDiscussion, MSG_TYPE
|
|
318
|
+
from ascii_colors import ASCIIColors
|
|
319
|
+
import json
|
|
320
|
+
|
|
321
|
+
# --- 1. Setup a persistent database for our discussion ---
|
|
322
|
+
db_manager = LollmsDataManager('sqlite:///my_assistant.db')
|
|
323
|
+
lc = LollmsClient(binding_name="ollama", model_name="llama3")
|
|
324
|
+
|
|
325
|
+
# Try to load an existing discussion or create a new one
|
|
326
|
+
discussion_id = "user_assistant_chat_1"
|
|
327
|
+
discussion = db_manager.get_discussion(lc, discussion_id)
|
|
328
|
+
if not discussion:
|
|
329
|
+
ASCIIColors.yellow("Creating a new discussion...")
|
|
330
|
+
discussion = LollmsDiscussion.create_new(
|
|
331
|
+
lollms_client=lc,
|
|
332
|
+
db_manager=db_manager,
|
|
333
|
+
id=discussion_id,
|
|
334
|
+
autosave=True # Important for persistence
|
|
335
|
+
)
|
|
336
|
+
# Let's preset some data in different zones
|
|
337
|
+
discussion.system_prompt = "You are a helpful Personal Assistant."
|
|
338
|
+
discussion.user_data_zone = "User's Name: Alex\nUser's Goal: Learn about AI development."
|
|
339
|
+
discussion.commit()
|
|
340
|
+
else:
|
|
341
|
+
ASCIIColors.green("Loaded existing discussion.")
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
def run_chat_turn(prompt: str):
|
|
345
|
+
"""Helper function to run a single chat turn and print details."""
|
|
346
|
+
ASCIIColors.cyan(f"\n> User: {prompt}")
|
|
347
|
+
|
|
348
|
+
# --- A. Check context status BEFORE the turn using get_context_status() ---
|
|
349
|
+
ASCIIColors.magenta("\n--- Context Status (Before Generation) ---")
|
|
350
|
+
status = discussion.get_context_status()
|
|
351
|
+
print(f"Max Tokens: {status.get('max_tokens')}, Current Tokens: {status.get('current_tokens')}")
|
|
352
|
+
|
|
353
|
+
# Print the system context details
|
|
354
|
+
if 'system_context' in status['zones']:
|
|
355
|
+
sys_ctx = status['zones']['system_context']
|
|
356
|
+
print(f" - System Context Tokens: {sys_ctx['tokens']}")
|
|
357
|
+
# The 'breakdown' shows the individual zones that were combined
|
|
358
|
+
for name, content in sys_ctx.get('breakdown', {}).items():
|
|
359
|
+
print(f" -> Contains '{name}': {content.split(chr(10))[0]}...")
|
|
360
|
+
|
|
361
|
+
# Print the message history details
|
|
362
|
+
if 'message_history' in status['zones']:
|
|
363
|
+
msg_hist = status['zones']['message_history']
|
|
364
|
+
print(f" - Message History Tokens: {msg_hist['tokens']} ({msg_hist['message_count']} messages)")
|
|
365
|
+
|
|
366
|
+
print("------------------------------------------")
|
|
367
|
+
|
|
368
|
+
# --- B. Run the chat ---
|
|
369
|
+
ASCIIColors.green("\n< Assistant:")
|
|
370
|
+
response = discussion.chat(
|
|
371
|
+
user_message=prompt,
|
|
372
|
+
streaming_callback=lambda chunk, type, **k: print(chunk, end="", flush=True) if type==MSG_TYPE.MSG_TYPE_CHUNK else None
|
|
373
|
+
)
|
|
374
|
+
print() # Newline after stream
|
|
375
|
+
|
|
376
|
+
# --- C. Trigger memorization to update the 'memory' zone ---
|
|
377
|
+
ASCIIColors.yellow("\nTriggering memorization process...")
|
|
378
|
+
discussion.memorize()
|
|
379
|
+
discussion.commit() # Save the new memory to the DB
|
|
380
|
+
ASCIIColors.yellow("Memorization complete.")
|
|
381
|
+
|
|
382
|
+
# --- Run a few turns ---
|
|
383
|
+
run_chat_turn("Hi there! Can you recommend a good Python library for building web APIs?")
|
|
384
|
+
run_chat_turn("That sounds great. By the way, my favorite programming language is Rust, I find its safety features amazing.")
|
|
385
|
+
run_chat_turn("What was my favorite programming language again?")
|
|
386
|
+
|
|
387
|
+
# --- Final Inspection of Memory ---
|
|
388
|
+
ASCIIColors.magenta("\n--- Final Context Status ---")
|
|
389
|
+
status = discussion.get_context_status()
|
|
390
|
+
print(f"Max Tokens: {status.get('max_tokens')}, Current Tokens: {status.get('current_tokens')}")
|
|
391
|
+
if 'system_context' in status['zones']:
|
|
392
|
+
sys_ctx = status['zones']['system_context']
|
|
393
|
+
print(f" - System Context Tokens: {sys_ctx['tokens']}")
|
|
394
|
+
for name, content in sys_ctx.get('breakdown', {}).items():
|
|
395
|
+
# Print the full content of the memory zone to verify it was updated
|
|
396
|
+
if name == 'memory':
|
|
397
|
+
ASCIIColors.yellow(f" -> Full '{name}' content:\n{content}")
|
|
398
|
+
else:
|
|
399
|
+
print(f" -> Contains '{name}': {content.split(chr(10))[0]}...")
|
|
400
|
+
print("------------------------------------------")
|
|
401
|
+
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
#### How it Works:
|
|
405
|
+
|
|
406
|
+
1. **Persistence & Initialization:** The `LollmsDataManager` saves and loads the discussion. We initialize the `system_prompt` and `user_data_zone` to provide initial context.
|
|
407
|
+
2. **`get_context_status()`:** Before each generation, we call this method. The output shows a `system_context` block with a token count for all combined zones and a `breakdown` field that lets us see the content of each individual zone that contributed to it.
|
|
408
|
+
3. **`memorize()`:** After the user mentions their favorite language, `memorize()` is called. The LLM analyzes the last turn, identifies this new, important fact, and appends it to the `discussion.memory` zone.
|
|
409
|
+
4. **Recall:** In the final turn, when asked to recall the favorite language, the AI has access to the updated `memory` content within its system context and can correctly answer "Rust". This demonstrates true long-term, stateful memory.
|
|
410
|
+
|
|
411
|
+
|
|
293
412
|
## Documentation
|
|
294
413
|
|
|
295
414
|
For more in-depth information, please refer to:
|
|
@@ -332,8 +451,8 @@ graph LR
|
|
|
332
451
|
* **LLM Bindings**: These are plugins that allow `LollmsClient` to communicate with different LLM backends. You choose a binding (e.g., `"ollama"`, `"lollms"`, `"pythonllamacpp"`) when you initialize `LollmsClient`.
|
|
333
452
|
* **🔧 MCP Bindings**: Enable tool use and function calling. `lollms-client` includes `local_mcp` for executing Python tools. It discovers tools from a specified folder (or uses its default set), each defined by a `.py` script and a `.mcp.json` metadata file.
|
|
334
453
|
* **Modality Bindings**: Similar to LLM bindings, but for services like Text-to-Speech (`tts`), Text-to-Image (`tti`), etc.
|
|
335
|
-
* **High-Level Operations**: Methods directly on `LollmsClient` (e.g., `sequential_summarize`, `deep_analyze`, `generate_code`, `yes_no`) for performing complex, multi-step AI tasks.
|
|
336
|
-
* **`LollmsDiscussion`**: Helps manage and format conversation histories for
|
|
454
|
+
* **High-Level Operations**: Methods directly on `LollmsClient` (e.g., `sequential_summarize`, `summarize`, `deep_analyze`, `generate_code`, `yes_no`) for performing complex, multi-step AI tasks.
|
|
455
|
+
* **`LollmsDiscussion`**: Helps manage and format conversation histories. Now includes sophisticated context layering through multiple data zones (`user_data_zone`, `discussion_data_zone`, `personality_data_zone`) and a long-term `memory` field for stateful, multi-session interactions.
|
|
337
456
|
|
|
338
457
|
## Examples
|
|
339
458
|
|
|
@@ -611,6 +730,58 @@ response = lc.generate_text("Write a short story about a robot who discovers mus
|
|
|
611
730
|
print(response)
|
|
612
731
|
```
|
|
613
732
|
|
|
733
|
+
### Sequential Summarization for Long Texts
|
|
734
|
+
|
|
735
|
+
When dealing with a document, article, or transcript that is too large to fit into a model's context window, the `summarize` method is the solution. It intelligently chunks the text, summarizes each piece, and then synthesizes those summaries into a final, coherent output.
|
|
736
|
+
|
|
737
|
+
```python
|
|
738
|
+
from lollms_client import LollmsClient, MSG_TYPE, LollmsPersonality
|
|
739
|
+
from ascii_colors import ASCIIColors
|
|
740
|
+
|
|
741
|
+
# --- A very long text (imagine this is 10,000+ tokens) ---
|
|
742
|
+
long_text = """
|
|
743
|
+
The history of computing is a fascinating journey from mechanical contraptions to the powerful devices we use today.
|
|
744
|
+
It began with devices like the abacus, used for arithmetic tasks. In the 19th century, Charles Babbage conceived
|
|
745
|
+
the Analytical Engine, a mechanical computer that was never fully built but laid the groundwork for modern computing.
|
|
746
|
+
...
|
|
747
|
+
(many, many paragraphs later)
|
|
748
|
+
...
|
|
749
|
+
Today, quantum computing promises to revolutionize the field once again, tackling problems currently intractable
|
|
750
|
+
for even the most powerful supercomputers. Researchers are exploring qubits and quantum entanglement to create
|
|
751
|
+
machines that will redefine what is computationally possible, impacting fields from medicine to materials science.
|
|
752
|
+
""" * 50 # Simulate a very long text
|
|
753
|
+
|
|
754
|
+
# --- Callback to see the process in action ---
|
|
755
|
+
def summary_callback(chunk: str, msg_type: MSG_TYPE, params: dict = None, **kwargs):
|
|
756
|
+
if msg_type in [MSG_TYPE.MSG_TYPE_STEP_START, MSG_TYPE.MSG_TYPE_STEP_END]:
|
|
757
|
+
ASCIIColors.yellow(f">> {chunk}")
|
|
758
|
+
elif msg_type == MSG_TYPE.MSG_TYPE_STEP:
|
|
759
|
+
ASCIIColors.cyan(f" {chunk}")
|
|
760
|
+
return True
|
|
761
|
+
|
|
762
|
+
try:
|
|
763
|
+
lc = LollmsClient(binding_name="ollama", model_name="llama3")
|
|
764
|
+
|
|
765
|
+
# The contextual prompt guides the focus of the summary
|
|
766
|
+
context_prompt = "Summarize the text, focusing on the key technological milestones and their inventors."
|
|
767
|
+
|
|
768
|
+
ASCIIColors.blue("--- Starting Sequential Summarization ---")
|
|
769
|
+
|
|
770
|
+
final_summary = lc.summarize(
|
|
771
|
+
text_to_summarize=long_text,
|
|
772
|
+
contextual_prompt=context_prompt,
|
|
773
|
+
chunk_size_tokens=1000, # Adjust based on your model's context size
|
|
774
|
+
overlap_tokens=200,
|
|
775
|
+
streaming_callback=summary_callback,
|
|
776
|
+
temperature=0.1 # Good for factual summarization
|
|
777
|
+
)
|
|
778
|
+
|
|
779
|
+
ASCIIColors.blue("\n--- Final Comprehensive Summary ---")
|
|
780
|
+
ASCIIColors.green(final_summary)
|
|
781
|
+
|
|
782
|
+
except Exception as e:
|
|
783
|
+
print(f"An error occurred: {e}")
|
|
784
|
+
```
|
|
614
785
|
## Contributing
|
|
615
786
|
|
|
616
787
|
Contributions are welcome! Whether it's bug reports, feature suggestions, documentation improvements, or new bindings, please feel free to open an issue or submit a pull request on our [GitHub repository](https://github.com/ParisNeo/lollms_client).
|
|
@@ -627,7 +798,6 @@ For a list of changes and updates, please refer to the [CHANGELOG.md](CHANGELOG.
|
|
|
627
798
|
---
|
|
628
799
|
### Phase 2: Update `docs/md/lollms_discussion.md`
|
|
629
800
|
|
|
630
|
-
`[UPDATE] docs/md/lollms_discussion.md`
|
|
631
801
|
```markdown
|
|
632
802
|
# LollmsDiscussion Class
|
|
633
803
|
|
|
@@ -646,7 +816,7 @@ A `LollmsDiscussion` can be either **in-memory** or **database-backed**, offerin
|
|
|
646
816
|
- **Branching:** The conversation is a tree, not a simple list. This allows for exploring different conversational paths from any point. You can regenerate an AI response, and it will create a new branch.
|
|
647
817
|
- **Context Exporting:** The `export()` method formats the conversation history for various LLM backends (`openai_chat`, `ollama_chat`, `lollms_text`, `markdown`), ensuring compatibility.
|
|
648
818
|
- **Automatic Pruning:** To prevent exceeding the model's context window, it can automatically summarize older parts of the conversation without losing the original data.
|
|
649
|
-
- **
|
|
819
|
+
- **Sophisticated Context Layering:** Manage conversation state with multiple, distinct data zones (`user_data_zone`, `discussion_data_zone`, `personality_data_zone`) and a long-term `memory` field, allowing for rich and persistent context.
|
|
650
820
|
|
|
651
821
|
## Creating a Discussion
|
|
652
822
|
|
|
@@ -671,56 +841,61 @@ discussion_db = LollmsDiscussion.create_new(
|
|
|
671
841
|
|
|
672
842
|
## Core Properties
|
|
673
843
|
|
|
674
|
-
###
|
|
844
|
+
### Data and Memory Zones
|
|
675
845
|
|
|
676
|
-
|
|
846
|
+
`LollmsDiscussion` moves beyond a single `data_zone` to a more structured system of context layers. These string properties allow you to inject specific, persistent information into the AI's system prompt, separate from the main conversational flow. The content of all non-empty zones is automatically formatted and included in the prompt.
|
|
677
847
|
|
|
678
|
-
|
|
848
|
+
#### `system_prompt`
|
|
849
|
+
The main instruction set for the AI's persona and core task. It's the foundation of the prompt.
|
|
850
|
+
- **Purpose:** Defines who the AI is and what its primary goal is.
|
|
851
|
+
- **Example:** `"You are a helpful and friendly assistant."`
|
|
679
852
|
|
|
680
|
-
####
|
|
853
|
+
#### `memory`
|
|
854
|
+
A special zone for storing long-term, cross-discussion information about the user or topics. It is designed to be built up over time.
|
|
855
|
+
- **Purpose:** To give the AI a persistent memory that survives across different chat sessions.
|
|
856
|
+
- **Example:** `"User's name is Alex.\nUser's favorite programming language is Rust."`
|
|
681
857
|
|
|
682
|
-
|
|
858
|
+
#### `user_data_zone`
|
|
859
|
+
Holds information specific to the current user that might be relevant for the session.
|
|
860
|
+
- **Purpose:** Storing user preferences, profile details, or session-specific goals.
|
|
861
|
+
-- **Example:** `"Current project: API development.\nUser is a beginner in Python."`
|
|
683
862
|
|
|
684
|
-
|
|
685
|
-
|
|
863
|
+
#### `discussion_data_zone`
|
|
864
|
+
Contains context relevant only to the current discussion.
|
|
865
|
+
- **Purpose:** Holding summaries, state information, or data relevant to the current conversation topic that needs to be kept in front of the AI.
|
|
866
|
+
- **Example:** `"The user has already tried libraries A and B and found them too complex."`
|
|
686
867
|
|
|
687
|
-
|
|
688
|
-
|
|
868
|
+
#### `personality_data_zone`
|
|
869
|
+
This is where static or dynamic knowledge from a `LollmsPersonality`'s `data_source` is loaded.
|
|
870
|
+
- **Purpose:** To provide personalities with their own built-in knowledge bases or rulesets.
|
|
871
|
+
- **Example:** `"Rule 1: All code must be documented.\nRule 2: Use type hints."`
|
|
689
872
|
|
|
690
|
-
|
|
691
|
-
discussion.system_prompt = "You are a Python expert. Help the user with their code."
|
|
692
|
-
discussion.data_zone = "# Current script content:\n\nimport os\n\ndef list_files(path):\n pass"
|
|
873
|
+
#### Example: How Zones are Combined
|
|
693
874
|
|
|
694
|
-
|
|
695
|
-
user_prompt = "Flesh out the list_files function to print all files in the given path."
|
|
875
|
+
The `export()` method intelligently combines these zones. If all zones were filled, the effective system prompt would look something like this:
|
|
696
876
|
|
|
697
|
-
# When you generate a response, the AI will see the system prompt AND the data_zone
|
|
698
|
-
# The effective system prompt becomes:
|
|
699
|
-
# """
|
|
700
|
-
# You are a Python expert. Help the user with their code.
|
|
701
|
-
#
|
|
702
|
-
# --- data ---
|
|
703
|
-
# # Current script content:
|
|
704
|
-
#
|
|
705
|
-
# import os
|
|
706
|
-
#
|
|
707
|
-
# def list_files(path):
|
|
708
|
-
# pass
|
|
709
|
-
# """
|
|
710
|
-
response = discussion.chat(user_prompt)
|
|
711
|
-
print(response['ai_message'].content)
|
|
712
|
-
|
|
713
|
-
# The calling application can then parse the AI's response and update the data_zone
|
|
714
|
-
# for the next turn.
|
|
715
|
-
updated_code = "# ... updated code from AI ...\nimport os\n\ndef list_files(path):\n for f in os.listdir(path):\n print(f)"
|
|
716
|
-
discussion.data_zone = updated_code
|
|
717
|
-
discussion.commit() # If DB-backed
|
|
718
877
|
```
|
|
878
|
+
!@>system:
|
|
879
|
+
You are a helpful and friendly assistant.
|
|
880
|
+
|
|
881
|
+
-- Memory --
|
|
882
|
+
User's name is Alex.
|
|
883
|
+
User's favorite programming language is Rust.
|
|
719
884
|
|
|
885
|
+
-- User Data Zone --
|
|
886
|
+
Current project: API development.
|
|
887
|
+
User is a beginner in Python.
|
|
888
|
+
|
|
889
|
+
-- Discussion Data Zone --
|
|
890
|
+
The user has already tried libraries A and B and found them too complex.
|
|
891
|
+
|
|
892
|
+
-- Personality Data Zone --
|
|
893
|
+
Rule 1: All code must be documented.
|
|
894
|
+
Rule 2: Use type hints.
|
|
895
|
+
```
|
|
720
896
|
### Other Important Properties
|
|
721
897
|
|
|
722
898
|
- `id`: The unique identifier for the discussion.
|
|
723
|
-
- `system_prompt`: The main system prompt defining the AI's persona and core instructions.
|
|
724
899
|
- `metadata`: A dictionary for storing any custom metadata, like a title.
|
|
725
900
|
- `active_branch_id`: The ID of the message at the "tip" of the current conversation branch.
|
|
726
901
|
- `messages`: A list of all `LollmsMessage` objects in the discussion.
|
|
@@ -745,15 +920,93 @@ The `chat` method intelligently handles tool activation and data loading when a
|
|
|
745
920
|
|
|
746
921
|
Before generation, the `chat` method checks for `personality.data_source`:
|
|
747
922
|
|
|
748
|
-
- **If it's a `str` (static data):** The string is
|
|
923
|
+
- **If it's a `str` (static data):** The string is loaded into the `discussion.personality_data_zone`, making it part of the system context for the current turn.
|
|
749
924
|
- **If it's a `Callable` (dynamic data):**
|
|
750
925
|
1. The AI first generates a query based on the current conversation.
|
|
751
926
|
2. The `chat` method calls your function with this query.
|
|
752
|
-
3. The returned string is
|
|
927
|
+
3. The returned string is loaded into the `discussion.personality_data_zone`.
|
|
753
928
|
4. The final response generation proceeds with this newly added context.
|
|
754
929
|
|
|
755
930
|
This makes it easy to create powerful, reusable agents. For a complete, runnable example of building a **Python Coder Agent** that uses both `active_mcps` and a static `data_source`, **please see the "Putting It All Together" section in the main `README.md` file.**
|
|
756
931
|
|
|
932
|
+
### New Methods for State and Context Management
|
|
933
|
+
|
|
934
|
+
#### `memorize()`
|
|
935
|
+
This method empowers the AI to build its own long-term memory. It analyzes the current conversation, extracts key facts or preferences, and appends them to the `memory` data zone.
|
|
936
|
+
|
|
937
|
+
- **How it works:** It uses the LLM itself to summarize the most important, long-term takeaways from the recent conversation.
|
|
938
|
+
- **Use Case:** Perfect for creating assistants that learn about the user over time, remembering their name, preferences, or past projects without the user needing to repeat themselves.
|
|
939
|
+
|
|
940
|
+
```python
|
|
941
|
+
# User has just said: "My company is called 'Innovatech'."
|
|
942
|
+
discussion.chat("My company is called 'Innovatech'.")
|
|
943
|
+
|
|
944
|
+
# Now, trigger memorization
|
|
945
|
+
discussion.memorize()
|
|
946
|
+
discussion.commit() # Save the updated memory to the database
|
|
947
|
+
|
|
948
|
+
# The discussion.memory field might now contain:
|
|
949
|
+
# "... previous memory ...
|
|
950
|
+
#
|
|
951
|
+
# --- Memory entry from 2024-06-27 10:30:00 UTC ---
|
|
952
|
+
# - User's company is named 'Innovatech'."
|
|
953
|
+
```
|
|
954
|
+
|
|
955
|
+
#### `get_context_status()`
|
|
956
|
+
|
|
957
|
+
Provides a detailed, real-time breakdown of the current prompt context, showing exactly what will be sent to the model and how many tokens each major component occupies. This is crucial for debugging context issues and understanding token usage.
|
|
958
|
+
|
|
959
|
+
The method accurately reflects the structure of the `lollms_text` format, where all system-level instructions (the main prompt, all data zones, and the pruning summary) are combined into a single system block.
|
|
960
|
+
|
|
961
|
+
- **Return Value:** A dictionary containing:
|
|
962
|
+
- `max_tokens`: The configured maximum token limit for the discussion.
|
|
963
|
+
- `current_tokens`: The total, most accurate token count for the entire prompt, calculated using the same logic as the `chat()` method.
|
|
964
|
+
- `zones`: A dictionary with up to two keys:
|
|
965
|
+
- **`system_context`**: Present if there is any system-level content. It contains:
|
|
966
|
+
- `tokens`: The total token count for the **entire combined system block** (e.g., `!@>system:\n...\n`).
|
|
967
|
+
- `content`: The full string content of the system block, showing exactly how all zones are merged.
|
|
968
|
+
- `breakdown`: A sub-dictionary showing the raw text of each individual component (e.g., `system_prompt`, `memory`, `user_data_zone`) that was used to build the `content`.
|
|
969
|
+
- **`message_history`**: Present if there are messages in the branch. It contains:
|
|
970
|
+
- `tokens`: The total token count for the message history part of the prompt.
|
|
971
|
+
- `content`: The full string of the formatted message history.
|
|
972
|
+
- `message_count`: The number of messages included in the history.
|
|
973
|
+
|
|
974
|
+
- **Use Case:** Essential for debugging context issues, visualizing how different data zones contribute to the final prompt, and monitoring token consumption.
|
|
975
|
+
|
|
976
|
+
```python
|
|
977
|
+
import json
|
|
978
|
+
|
|
979
|
+
# Assuming 'discussion' is an LollmsDiscussion object with some data
|
|
980
|
+
discussion.system_prompt = "You are a helpful AI."
|
|
981
|
+
discussion.user_data_zone = "User is named Bob."
|
|
982
|
+
discussion.add_message(sender="user", content="Hello!")
|
|
983
|
+
discussion.add_message(sender="assistant", content="Hi Bob!")
|
|
984
|
+
|
|
985
|
+
status = discussion.get_context_status()
|
|
986
|
+
print(json.dumps(status, indent=2))
|
|
987
|
+
|
|
988
|
+
# Expected Output Structure:
|
|
989
|
+
# {
|
|
990
|
+
# "max_tokens": null,
|
|
991
|
+
# "current_tokens": 46,
|
|
992
|
+
# "zones": {
|
|
993
|
+
# "system_context": {
|
|
994
|
+
# "content": "You are a helpful AI.\n\n-- User Data Zone --\nUser is named Bob.",
|
|
995
|
+
# "tokens": 25,
|
|
996
|
+
# "breakdown": {
|
|
997
|
+
# "system_prompt": "You are a helpful AI.",
|
|
998
|
+
# "user_data_zone": "User is named Bob."
|
|
999
|
+
# }
|
|
1000
|
+
# },
|
|
1001
|
+
# "message_history": {
|
|
1002
|
+
# "content": "!@>user:\nHello!\n!@>assistant:\nHi Bob!\n",
|
|
1003
|
+
# "tokens": 21,
|
|
1004
|
+
# "message_count": 2
|
|
1005
|
+
# }
|
|
1006
|
+
# }
|
|
1007
|
+
# }
|
|
1008
|
+
```
|
|
1009
|
+
|
|
757
1010
|
### Other Methods
|
|
758
1011
|
- `add_message(sender, content, ...)`: Adds a new message.
|
|
759
1012
|
- `export(format_type, ...)`: Exports the discussion to a specific format.
|