lollms-client 0.29.3__tar.gz → 0.31.0__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.3 → lollms_client-0.31.0}/PKG-INFO +61 -222
- {lollms_client-0.29.3 → lollms_client-0.31.0}/README.md +60 -221
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/__init__.py +1 -1
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/llm_bindings/ollama/__init__.py +19 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/lollms_core.py +115 -49
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/lollms_discussion.py +428 -32
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/lollms_llm_binding.py +17 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/lollms_utilities.py +136 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client.egg-info/PKG-INFO +61 -222
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client.egg-info/SOURCES.txt +2 -1
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client.egg-info/top_level.txt +1 -0
- lollms_client-0.31.0/test/test_lollms_discussion.py +368 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/LICENSE +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/article_summary/article_summary.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/console_discussion/console_app.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/console_discussion.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/deep_analyze/deep_analyse.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/deep_analyze/deep_analyze_multiple_files.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/function_calling_with_local_custom_mcp.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/generate_a_benchmark_for_safe_store.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/generate_and_speak/generate_and_speak.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/generate_game_sfx/generate_game_fx.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/generate_text_with_multihop_rag_example.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/gradio_chat_app.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/gradio_lollms_chat.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/internet_search_with_rag.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/lollms_chat/calculator.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/lollms_chat/derivative.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/lollms_chat/test_openai_compatible_with_lollms_chat.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/lollms_discussions_test.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/mcp_examples/external_mcp.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/mcp_examples/local_mcp.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/mcp_examples/openai_mcp.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/mcp_examples/run_remote_mcp_example_v2.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/mcp_examples/run_standard_mcp_example.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/simple_text_gen_test.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/simple_text_gen_with_image_test.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/test_local_models/local_chat.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/text_2_audio.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/text_2_image.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/text_2_image_diffusers.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/text_and_image_2_audio.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/text_gen.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/examples/text_gen_system_prompt.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/llm_bindings/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/llm_bindings/azure_openai/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/llm_bindings/claude/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/llm_bindings/gemini/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/llm_bindings/grok/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/llm_bindings/groq/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/llm_bindings/hugging_face_inference_api/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/llm_bindings/litellm/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/llm_bindings/llamacpp/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/llm_bindings/lollms/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/llm_bindings/lollms_webui/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/llm_bindings/mistral/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/llm_bindings/open_router/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/llm_bindings/openai/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/llm_bindings/openllm/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/llm_bindings/pythonllamacpp/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/llm_bindings/tensor_rt/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/llm_bindings/transformers/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/llm_bindings/vllm/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/lollms_config.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/lollms_js_analyzer.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/lollms_mcp_binding.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/lollms_personality.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/lollms_python_analyzer.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/lollms_stt_binding.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/lollms_tti_binding.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/lollms_ttm_binding.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/lollms_tts_binding.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/lollms_ttv_binding.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/lollms_types.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/mcp_bindings/local_mcp/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/mcp_bindings/local_mcp/default_tools/file_writer/file_writer.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/mcp_bindings/local_mcp/default_tools/generate_image_from_prompt/generate_image_from_prompt.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/mcp_bindings/local_mcp/default_tools/internet_search/internet_search.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/mcp_bindings/local_mcp/default_tools/python_interpreter/python_interpreter.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/mcp_bindings/remote_mcp/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/mcp_bindings/standard_mcp/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/stt_bindings/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/stt_bindings/lollms/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/stt_bindings/whisper/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/stt_bindings/whispercpp/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/tti_bindings/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/tti_bindings/dalle/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/tti_bindings/diffusers/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/tti_bindings/gemini/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/tti_bindings/lollms/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/ttm_bindings/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/ttm_bindings/audiocraft/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/ttm_bindings/bark/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/ttm_bindings/lollms/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/tts_bindings/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/tts_bindings/bark/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/tts_bindings/lollms/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/tts_bindings/piper_tts/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/tts_bindings/xtts/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/ttv_bindings/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client/ttv_bindings/lollms/__init__.py +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client.egg-info/dependency_links.txt +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/lollms_client.egg-info/requires.txt +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/pyproject.toml +0 -0
- {lollms_client-0.29.3 → lollms_client-0.31.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lollms_client
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.31.0
|
|
4
4
|
Summary: A client library for LoLLMs generate endpoint
|
|
5
5
|
Author-email: ParisNeo <parisneoai@gmail.com>
|
|
6
6
|
License: Apache Software License
|
|
@@ -48,6 +48,7 @@ Whether you're connecting to a remote LoLLMs server, an Ollama instance, the Ope
|
|
|
48
48
|
|
|
49
49
|
* 🔌 **Versatile Binding System:** Seamlessly switch between different LLM backends (LoLLMs, Ollama, OpenAI, Llama.cpp, Transformers, vLLM, OpenLLM) without major code changes.
|
|
50
50
|
* 🗣️ **Multimodal Support:** Interact with models capable of processing images and generate various outputs like speech (TTS) and images (TTI).
|
|
51
|
+
* 🖼️ **Selective Image Activation:** Control which images in a message are active and sent to the model, allowing for fine-grained multimodal context management without deleting the original data.
|
|
51
52
|
* 🤖 **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
53
|
* 🎭 **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
54
|
* 🚀 **Streaming & Callbacks:** Efficiently handle real-time text generation with customizable callback functions, including during MCP interactions.
|
|
@@ -408,6 +409,64 @@ print("------------------------------------------")
|
|
|
408
409
|
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
410
|
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
|
|
|
412
|
+
### Managing Multimodal Context: Activating and Deactivating Images
|
|
413
|
+
|
|
414
|
+
When working with multimodal models, you can now control which images in a message are active and sent to the model. This is useful for focusing the AI's attention, saving tokens on expensive vision models, or allowing a user to correct which images are relevant.
|
|
415
|
+
|
|
416
|
+
This is managed at the `LollmsMessage` level using the `toggle_image_activation()` method.
|
|
417
|
+
|
|
418
|
+
```python
|
|
419
|
+
from lollms_client import LollmsClient, LollmsDiscussion, LollmsDataManager
|
|
420
|
+
from ascii_colors import ASCIIColors
|
|
421
|
+
import base64
|
|
422
|
+
from pathlib import Path
|
|
423
|
+
|
|
424
|
+
# Helper to create a dummy image b64 string
|
|
425
|
+
def create_dummy_image(text):
|
|
426
|
+
from PIL import Image, ImageDraw
|
|
427
|
+
img = Image.new('RGB', (100, 30), color = (73, 109, 137))
|
|
428
|
+
d = ImageDraw.Draw(img)
|
|
429
|
+
d.text((10,10), text, fill=(255,255,0))
|
|
430
|
+
buffer = Path("temp_img.png")
|
|
431
|
+
img.save(buffer, "PNG")
|
|
432
|
+
b64 = base64.b64encode(buffer.read_bytes()).decode('utf-8')
|
|
433
|
+
buffer.unlink()
|
|
434
|
+
return b64
|
|
435
|
+
|
|
436
|
+
# --- 1. Setup ---
|
|
437
|
+
lc = LollmsClient(binding_name="ollama", model_name="llava")
|
|
438
|
+
discussion = LollmsDiscussion.create_new(lollms_client=lc)
|
|
439
|
+
|
|
440
|
+
# --- 2. Add a message with multiple images ---
|
|
441
|
+
img1_b64 = create_dummy_image("Image 1")
|
|
442
|
+
img2_b64 = create_dummy_image("Image 2: Cat")
|
|
443
|
+
img3_b64 = create_dummy_image("Image 3")
|
|
444
|
+
|
|
445
|
+
discussion.add_message(
|
|
446
|
+
sender="user",
|
|
447
|
+
content="What is in the second image?",
|
|
448
|
+
images=[img1_b64, img2_b64, img3_b64]
|
|
449
|
+
)
|
|
450
|
+
user_message = discussion.get_messages()[-1]
|
|
451
|
+
|
|
452
|
+
# --- 3. Check the initial state ---
|
|
453
|
+
ASCIIColors.magenta("--- Initial State (All 3 Images Active) ---")
|
|
454
|
+
status_before = discussion.get_context_status()
|
|
455
|
+
print(f"Message History Text:\n{status_before['zones']['message_history']['content']}")
|
|
456
|
+
|
|
457
|
+
# --- 4. Deactivate irrelevant images ---
|
|
458
|
+
ASCIIColors.magenta("\n--- Deactivating images 1 and 3 ---")
|
|
459
|
+
user_message.toggle_image_activation(index=0, active=False) # Deactivate first image
|
|
460
|
+
user_message.toggle_image_activation(index=2, active=False) # Deactivate third image
|
|
461
|
+
|
|
462
|
+
# --- 5. Check the new state ---
|
|
463
|
+
ASCIIColors.magenta("\n--- New State (Only Image 2 is Active) ---")
|
|
464
|
+
status_after = discussion.get_context_status()
|
|
465
|
+
print(f"Message History Text:\n{status_after['zones']['message_history']['content']}")
|
|
466
|
+
|
|
467
|
+
ASCIIColors.green("\nNotice the message now says '(1 image(s) attached)' instead of 3.")
|
|
468
|
+
ASCIIColors.green("Only the active image will be sent to the multimodal LLM.")
|
|
469
|
+
```
|
|
411
470
|
|
|
412
471
|
## Documentation
|
|
413
472
|
|
|
@@ -788,228 +847,8 @@ Contributions are welcome! Whether it's bug reports, feature suggestions, docume
|
|
|
788
847
|
|
|
789
848
|
## License
|
|
790
849
|
|
|
791
|
-
This project is licensed under the **Apache 2.0 License**. See the [LICENSE](LICENSE) file for details
|
|
850
|
+
This project is licensed under the **Apache 2.0 License**. See the [LICENSE](LICENSE) file for details.
|
|
792
851
|
|
|
793
852
|
## Changelog
|
|
794
853
|
|
|
795
854
|
For a list of changes and updates, please refer to the [CHANGELOG.md](CHANGELOG.md) file.
|
|
796
|
-
```
|
|
797
|
-
|
|
798
|
-
---
|
|
799
|
-
### Phase 2: Update `docs/md/lollms_discussion.md`
|
|
800
|
-
|
|
801
|
-
```markdown
|
|
802
|
-
# LollmsDiscussion Class
|
|
803
|
-
|
|
804
|
-
The `LollmsDiscussion` class is a cornerstone of the `lollms-client` library, designed to represent and manage a single conversation. It provides a robust interface for handling message history, conversation branching, context formatting, and persistence.
|
|
805
|
-
|
|
806
|
-
## Overview
|
|
807
|
-
|
|
808
|
-
A `LollmsDiscussion` can be either **in-memory** or **database-backed**, offering flexibility for different use cases.
|
|
809
|
-
|
|
810
|
-
- **In-Memory:** Ideal for temporary or transient conversations. The discussion exists only for the duration of the application's runtime.
|
|
811
|
-
- **Database-Backed:** Provides persistence by saving the entire conversation, including all branches and metadata, to a database file (e.g., SQLite). This is perfect for applications that need to retain user chat history.
|
|
812
|
-
|
|
813
|
-
## Key Features
|
|
814
|
-
|
|
815
|
-
- **Message Management:** Add user and AI messages, which are automatically linked to form a conversation tree.
|
|
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.
|
|
817
|
-
- **Context Exporting:** The `export()` method formats the conversation history for various LLM backends (`openai_chat`, `ollama_chat`, `lollms_text`, `markdown`), ensuring compatibility.
|
|
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.
|
|
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.
|
|
820
|
-
|
|
821
|
-
## Creating a Discussion
|
|
822
|
-
|
|
823
|
-
The recommended way to create a discussion is using the `LollmsDiscussion.create_new()` class method.
|
|
824
|
-
|
|
825
|
-
```python
|
|
826
|
-
from lollms_client import LollmsClient, LollmsDataManager, LollmsDiscussion
|
|
827
|
-
|
|
828
|
-
# For an in-memory discussion (lost when the app closes)
|
|
829
|
-
lc = LollmsClient(binding_name="ollama", model_name="llama3")
|
|
830
|
-
discussion = LollmsDiscussion.create_new(lollms_client=lc, id="my-temp-discussion")
|
|
831
|
-
|
|
832
|
-
# For a persistent, database-backed discussion
|
|
833
|
-
# This will create a 'discussions.db' file if it doesn't exist
|
|
834
|
-
db_manager = LollmsDataManager('sqlite:///discussions.db')
|
|
835
|
-
discussion_db = LollmsDiscussion.create_new(
|
|
836
|
-
lollms_client=lc,
|
|
837
|
-
db_manager=db_manager,
|
|
838
|
-
discussion_metadata={"title": "My First DB Chat"}
|
|
839
|
-
)
|
|
840
|
-
```
|
|
841
|
-
|
|
842
|
-
## Core Properties
|
|
843
|
-
|
|
844
|
-
### Data and Memory Zones
|
|
845
|
-
|
|
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.
|
|
847
|
-
|
|
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."`
|
|
852
|
-
|
|
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."`
|
|
857
|
-
|
|
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."`
|
|
862
|
-
|
|
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."`
|
|
867
|
-
|
|
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."`
|
|
872
|
-
|
|
873
|
-
#### Example: How Zones are Combined
|
|
874
|
-
|
|
875
|
-
The `export()` method intelligently combines these zones. If all zones were filled, the effective system prompt would look something like this:
|
|
876
|
-
|
|
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.
|
|
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
|
-
```
|
|
896
|
-
### Other Important Properties
|
|
897
|
-
|
|
898
|
-
- `id`: The unique identifier for the discussion.
|
|
899
|
-
- `metadata`: A dictionary for storing any custom metadata, like a title.
|
|
900
|
-
- `active_branch_id`: The ID of the message at the "tip" of the current conversation branch.
|
|
901
|
-
- `messages`: A list of all `LollmsMessage` objects in the discussion.
|
|
902
|
-
|
|
903
|
-
## Main Methods
|
|
904
|
-
|
|
905
|
-
### `chat()`
|
|
906
|
-
The `chat()` method is the primary way to interact with the discussion. It handles a full user-to-AI turn, including invoking the advanced agentic capabilities of the `LollmsClient`.
|
|
907
|
-
|
|
908
|
-
#### Personalities, Tools, and Data Sources
|
|
909
|
-
|
|
910
|
-
The `chat` method intelligently handles tool activation and data loading when a `LollmsPersonality` is provided. This allows personalities to be configured as self-contained agents with their own default tools and knowledge bases.
|
|
911
|
-
|
|
912
|
-
**Tool Activation (`use_mcps`):**
|
|
913
|
-
|
|
914
|
-
1. **Personality has tools, `use_mcps` is not set:** The agent will use the tools defined in `personality.active_mcps`.
|
|
915
|
-
2. **Personality has tools, `use_mcps` is also set:** The agent will use a *combination* of tools from both the personality and the `use_mcps` parameter for that specific turn. Duplicates are automatically handled. This allows you to augment a personality's default tools on the fly.
|
|
916
|
-
3. **Personality has no tools, `use_mcps` is set:** The agent will use only the tools specified in the `use_mcps` parameter.
|
|
917
|
-
4. **Neither are set:** The agentic turn is not triggered (unless a data store is used), and a simple chat generation occurs.
|
|
918
|
-
|
|
919
|
-
**Knowledge Loading (`data_source`):**
|
|
920
|
-
|
|
921
|
-
Before generation, the `chat` method checks for `personality.data_source`:
|
|
922
|
-
|
|
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.
|
|
924
|
-
- **If it's a `Callable` (dynamic data):**
|
|
925
|
-
1. The AI first generates a query based on the current conversation.
|
|
926
|
-
2. The `chat` method calls your function with this query.
|
|
927
|
-
3. The returned string is loaded into the `discussion.personality_data_zone`.
|
|
928
|
-
4. The final response generation proceeds with this newly added context.
|
|
929
|
-
|
|
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.**
|
|
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
|
-
|
|
1010
|
-
### Other Methods
|
|
1011
|
-
- `add_message(sender, content, ...)`: Adds a new message.
|
|
1012
|
-
- `export(format_type, ...)`: Exports the discussion to a specific format.
|
|
1013
|
-
- `commit()`: Saves changes to the database (if DB-backed).
|
|
1014
|
-
- `summarize_and_prune()`: Automatically handles context window limits.
|
|
1015
|
-
- `count_discussion_tokens()`: Counts the tokens for a given format.
|
|
@@ -17,6 +17,7 @@ Whether you're connecting to a remote LoLLMs server, an Ollama instance, the Ope
|
|
|
17
17
|
|
|
18
18
|
* 🔌 **Versatile Binding System:** Seamlessly switch between different LLM backends (LoLLMs, Ollama, OpenAI, Llama.cpp, Transformers, vLLM, OpenLLM) without major code changes.
|
|
19
19
|
* 🗣️ **Multimodal Support:** Interact with models capable of processing images and generate various outputs like speech (TTS) and images (TTI).
|
|
20
|
+
* 🖼️ **Selective Image Activation:** Control which images in a message are active and sent to the model, allowing for fine-grained multimodal context management without deleting the original data.
|
|
20
21
|
* 🤖 **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).
|
|
21
22
|
* 🎭 **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.
|
|
22
23
|
* 🚀 **Streaming & Callbacks:** Efficiently handle real-time text generation with customizable callback functions, including during MCP interactions.
|
|
@@ -377,6 +378,64 @@ print("------------------------------------------")
|
|
|
377
378
|
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.
|
|
378
379
|
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.
|
|
379
380
|
|
|
381
|
+
### Managing Multimodal Context: Activating and Deactivating Images
|
|
382
|
+
|
|
383
|
+
When working with multimodal models, you can now control which images in a message are active and sent to the model. This is useful for focusing the AI's attention, saving tokens on expensive vision models, or allowing a user to correct which images are relevant.
|
|
384
|
+
|
|
385
|
+
This is managed at the `LollmsMessage` level using the `toggle_image_activation()` method.
|
|
386
|
+
|
|
387
|
+
```python
|
|
388
|
+
from lollms_client import LollmsClient, LollmsDiscussion, LollmsDataManager
|
|
389
|
+
from ascii_colors import ASCIIColors
|
|
390
|
+
import base64
|
|
391
|
+
from pathlib import Path
|
|
392
|
+
|
|
393
|
+
# Helper to create a dummy image b64 string
|
|
394
|
+
def create_dummy_image(text):
|
|
395
|
+
from PIL import Image, ImageDraw
|
|
396
|
+
img = Image.new('RGB', (100, 30), color = (73, 109, 137))
|
|
397
|
+
d = ImageDraw.Draw(img)
|
|
398
|
+
d.text((10,10), text, fill=(255,255,0))
|
|
399
|
+
buffer = Path("temp_img.png")
|
|
400
|
+
img.save(buffer, "PNG")
|
|
401
|
+
b64 = base64.b64encode(buffer.read_bytes()).decode('utf-8')
|
|
402
|
+
buffer.unlink()
|
|
403
|
+
return b64
|
|
404
|
+
|
|
405
|
+
# --- 1. Setup ---
|
|
406
|
+
lc = LollmsClient(binding_name="ollama", model_name="llava")
|
|
407
|
+
discussion = LollmsDiscussion.create_new(lollms_client=lc)
|
|
408
|
+
|
|
409
|
+
# --- 2. Add a message with multiple images ---
|
|
410
|
+
img1_b64 = create_dummy_image("Image 1")
|
|
411
|
+
img2_b64 = create_dummy_image("Image 2: Cat")
|
|
412
|
+
img3_b64 = create_dummy_image("Image 3")
|
|
413
|
+
|
|
414
|
+
discussion.add_message(
|
|
415
|
+
sender="user",
|
|
416
|
+
content="What is in the second image?",
|
|
417
|
+
images=[img1_b64, img2_b64, img3_b64]
|
|
418
|
+
)
|
|
419
|
+
user_message = discussion.get_messages()[-1]
|
|
420
|
+
|
|
421
|
+
# --- 3. Check the initial state ---
|
|
422
|
+
ASCIIColors.magenta("--- Initial State (All 3 Images Active) ---")
|
|
423
|
+
status_before = discussion.get_context_status()
|
|
424
|
+
print(f"Message History Text:\n{status_before['zones']['message_history']['content']}")
|
|
425
|
+
|
|
426
|
+
# --- 4. Deactivate irrelevant images ---
|
|
427
|
+
ASCIIColors.magenta("\n--- Deactivating images 1 and 3 ---")
|
|
428
|
+
user_message.toggle_image_activation(index=0, active=False) # Deactivate first image
|
|
429
|
+
user_message.toggle_image_activation(index=2, active=False) # Deactivate third image
|
|
430
|
+
|
|
431
|
+
# --- 5. Check the new state ---
|
|
432
|
+
ASCIIColors.magenta("\n--- New State (Only Image 2 is Active) ---")
|
|
433
|
+
status_after = discussion.get_context_status()
|
|
434
|
+
print(f"Message History Text:\n{status_after['zones']['message_history']['content']}")
|
|
435
|
+
|
|
436
|
+
ASCIIColors.green("\nNotice the message now says '(1 image(s) attached)' instead of 3.")
|
|
437
|
+
ASCIIColors.green("Only the active image will be sent to the multimodal LLM.")
|
|
438
|
+
```
|
|
380
439
|
|
|
381
440
|
## Documentation
|
|
382
441
|
|
|
@@ -757,228 +816,8 @@ Contributions are welcome! Whether it's bug reports, feature suggestions, docume
|
|
|
757
816
|
|
|
758
817
|
## License
|
|
759
818
|
|
|
760
|
-
This project is licensed under the **Apache 2.0 License**. See the [LICENSE](LICENSE) file for details
|
|
819
|
+
This project is licensed under the **Apache 2.0 License**. See the [LICENSE](LICENSE) file for details.
|
|
761
820
|
|
|
762
821
|
## Changelog
|
|
763
822
|
|
|
764
823
|
For a list of changes and updates, please refer to the [CHANGELOG.md](CHANGELOG.md) file.
|
|
765
|
-
```
|
|
766
|
-
|
|
767
|
-
---
|
|
768
|
-
### Phase 2: Update `docs/md/lollms_discussion.md`
|
|
769
|
-
|
|
770
|
-
```markdown
|
|
771
|
-
# LollmsDiscussion Class
|
|
772
|
-
|
|
773
|
-
The `LollmsDiscussion` class is a cornerstone of the `lollms-client` library, designed to represent and manage a single conversation. It provides a robust interface for handling message history, conversation branching, context formatting, and persistence.
|
|
774
|
-
|
|
775
|
-
## Overview
|
|
776
|
-
|
|
777
|
-
A `LollmsDiscussion` can be either **in-memory** or **database-backed**, offering flexibility for different use cases.
|
|
778
|
-
|
|
779
|
-
- **In-Memory:** Ideal for temporary or transient conversations. The discussion exists only for the duration of the application's runtime.
|
|
780
|
-
- **Database-Backed:** Provides persistence by saving the entire conversation, including all branches and metadata, to a database file (e.g., SQLite). This is perfect for applications that need to retain user chat history.
|
|
781
|
-
|
|
782
|
-
## Key Features
|
|
783
|
-
|
|
784
|
-
- **Message Management:** Add user and AI messages, which are automatically linked to form a conversation tree.
|
|
785
|
-
- **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.
|
|
786
|
-
- **Context Exporting:** The `export()` method formats the conversation history for various LLM backends (`openai_chat`, `ollama_chat`, `lollms_text`, `markdown`), ensuring compatibility.
|
|
787
|
-
- **Automatic Pruning:** To prevent exceeding the model's context window, it can automatically summarize older parts of the conversation without losing the original data.
|
|
788
|
-
- **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.
|
|
789
|
-
|
|
790
|
-
## Creating a Discussion
|
|
791
|
-
|
|
792
|
-
The recommended way to create a discussion is using the `LollmsDiscussion.create_new()` class method.
|
|
793
|
-
|
|
794
|
-
```python
|
|
795
|
-
from lollms_client import LollmsClient, LollmsDataManager, LollmsDiscussion
|
|
796
|
-
|
|
797
|
-
# For an in-memory discussion (lost when the app closes)
|
|
798
|
-
lc = LollmsClient(binding_name="ollama", model_name="llama3")
|
|
799
|
-
discussion = LollmsDiscussion.create_new(lollms_client=lc, id="my-temp-discussion")
|
|
800
|
-
|
|
801
|
-
# For a persistent, database-backed discussion
|
|
802
|
-
# This will create a 'discussions.db' file if it doesn't exist
|
|
803
|
-
db_manager = LollmsDataManager('sqlite:///discussions.db')
|
|
804
|
-
discussion_db = LollmsDiscussion.create_new(
|
|
805
|
-
lollms_client=lc,
|
|
806
|
-
db_manager=db_manager,
|
|
807
|
-
discussion_metadata={"title": "My First DB Chat"}
|
|
808
|
-
)
|
|
809
|
-
```
|
|
810
|
-
|
|
811
|
-
## Core Properties
|
|
812
|
-
|
|
813
|
-
### Data and Memory Zones
|
|
814
|
-
|
|
815
|
-
`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.
|
|
816
|
-
|
|
817
|
-
#### `system_prompt`
|
|
818
|
-
The main instruction set for the AI's persona and core task. It's the foundation of the prompt.
|
|
819
|
-
- **Purpose:** Defines who the AI is and what its primary goal is.
|
|
820
|
-
- **Example:** `"You are a helpful and friendly assistant."`
|
|
821
|
-
|
|
822
|
-
#### `memory`
|
|
823
|
-
A special zone for storing long-term, cross-discussion information about the user or topics. It is designed to be built up over time.
|
|
824
|
-
- **Purpose:** To give the AI a persistent memory that survives across different chat sessions.
|
|
825
|
-
- **Example:** `"User's name is Alex.\nUser's favorite programming language is Rust."`
|
|
826
|
-
|
|
827
|
-
#### `user_data_zone`
|
|
828
|
-
Holds information specific to the current user that might be relevant for the session.
|
|
829
|
-
- **Purpose:** Storing user preferences, profile details, or session-specific goals.
|
|
830
|
-
-- **Example:** `"Current project: API development.\nUser is a beginner in Python."`
|
|
831
|
-
|
|
832
|
-
#### `discussion_data_zone`
|
|
833
|
-
Contains context relevant only to the current discussion.
|
|
834
|
-
- **Purpose:** Holding summaries, state information, or data relevant to the current conversation topic that needs to be kept in front of the AI.
|
|
835
|
-
- **Example:** `"The user has already tried libraries A and B and found them too complex."`
|
|
836
|
-
|
|
837
|
-
#### `personality_data_zone`
|
|
838
|
-
This is where static or dynamic knowledge from a `LollmsPersonality`'s `data_source` is loaded.
|
|
839
|
-
- **Purpose:** To provide personalities with their own built-in knowledge bases or rulesets.
|
|
840
|
-
- **Example:** `"Rule 1: All code must be documented.\nRule 2: Use type hints."`
|
|
841
|
-
|
|
842
|
-
#### Example: How Zones are Combined
|
|
843
|
-
|
|
844
|
-
The `export()` method intelligently combines these zones. If all zones were filled, the effective system prompt would look something like this:
|
|
845
|
-
|
|
846
|
-
```
|
|
847
|
-
!@>system:
|
|
848
|
-
You are a helpful and friendly assistant.
|
|
849
|
-
|
|
850
|
-
-- Memory --
|
|
851
|
-
User's name is Alex.
|
|
852
|
-
User's favorite programming language is Rust.
|
|
853
|
-
|
|
854
|
-
-- User Data Zone --
|
|
855
|
-
Current project: API development.
|
|
856
|
-
User is a beginner in Python.
|
|
857
|
-
|
|
858
|
-
-- Discussion Data Zone --
|
|
859
|
-
The user has already tried libraries A and B and found them too complex.
|
|
860
|
-
|
|
861
|
-
-- Personality Data Zone --
|
|
862
|
-
Rule 1: All code must be documented.
|
|
863
|
-
Rule 2: Use type hints.
|
|
864
|
-
```
|
|
865
|
-
### Other Important Properties
|
|
866
|
-
|
|
867
|
-
- `id`: The unique identifier for the discussion.
|
|
868
|
-
- `metadata`: A dictionary for storing any custom metadata, like a title.
|
|
869
|
-
- `active_branch_id`: The ID of the message at the "tip" of the current conversation branch.
|
|
870
|
-
- `messages`: A list of all `LollmsMessage` objects in the discussion.
|
|
871
|
-
|
|
872
|
-
## Main Methods
|
|
873
|
-
|
|
874
|
-
### `chat()`
|
|
875
|
-
The `chat()` method is the primary way to interact with the discussion. It handles a full user-to-AI turn, including invoking the advanced agentic capabilities of the `LollmsClient`.
|
|
876
|
-
|
|
877
|
-
#### Personalities, Tools, and Data Sources
|
|
878
|
-
|
|
879
|
-
The `chat` method intelligently handles tool activation and data loading when a `LollmsPersonality` is provided. This allows personalities to be configured as self-contained agents with their own default tools and knowledge bases.
|
|
880
|
-
|
|
881
|
-
**Tool Activation (`use_mcps`):**
|
|
882
|
-
|
|
883
|
-
1. **Personality has tools, `use_mcps` is not set:** The agent will use the tools defined in `personality.active_mcps`.
|
|
884
|
-
2. **Personality has tools, `use_mcps` is also set:** The agent will use a *combination* of tools from both the personality and the `use_mcps` parameter for that specific turn. Duplicates are automatically handled. This allows you to augment a personality's default tools on the fly.
|
|
885
|
-
3. **Personality has no tools, `use_mcps` is set:** The agent will use only the tools specified in the `use_mcps` parameter.
|
|
886
|
-
4. **Neither are set:** The agentic turn is not triggered (unless a data store is used), and a simple chat generation occurs.
|
|
887
|
-
|
|
888
|
-
**Knowledge Loading (`data_source`):**
|
|
889
|
-
|
|
890
|
-
Before generation, the `chat` method checks for `personality.data_source`:
|
|
891
|
-
|
|
892
|
-
- **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.
|
|
893
|
-
- **If it's a `Callable` (dynamic data):**
|
|
894
|
-
1. The AI first generates a query based on the current conversation.
|
|
895
|
-
2. The `chat` method calls your function with this query.
|
|
896
|
-
3. The returned string is loaded into the `discussion.personality_data_zone`.
|
|
897
|
-
4. The final response generation proceeds with this newly added context.
|
|
898
|
-
|
|
899
|
-
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.**
|
|
900
|
-
|
|
901
|
-
### New Methods for State and Context Management
|
|
902
|
-
|
|
903
|
-
#### `memorize()`
|
|
904
|
-
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.
|
|
905
|
-
|
|
906
|
-
- **How it works:** It uses the LLM itself to summarize the most important, long-term takeaways from the recent conversation.
|
|
907
|
-
- **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.
|
|
908
|
-
|
|
909
|
-
```python
|
|
910
|
-
# User has just said: "My company is called 'Innovatech'."
|
|
911
|
-
discussion.chat("My company is called 'Innovatech'.")
|
|
912
|
-
|
|
913
|
-
# Now, trigger memorization
|
|
914
|
-
discussion.memorize()
|
|
915
|
-
discussion.commit() # Save the updated memory to the database
|
|
916
|
-
|
|
917
|
-
# The discussion.memory field might now contain:
|
|
918
|
-
# "... previous memory ...
|
|
919
|
-
#
|
|
920
|
-
# --- Memory entry from 2024-06-27 10:30:00 UTC ---
|
|
921
|
-
# - User's company is named 'Innovatech'."
|
|
922
|
-
```
|
|
923
|
-
|
|
924
|
-
#### `get_context_status()`
|
|
925
|
-
|
|
926
|
-
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.
|
|
927
|
-
|
|
928
|
-
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.
|
|
929
|
-
|
|
930
|
-
- **Return Value:** A dictionary containing:
|
|
931
|
-
- `max_tokens`: The configured maximum token limit for the discussion.
|
|
932
|
-
- `current_tokens`: The total, most accurate token count for the entire prompt, calculated using the same logic as the `chat()` method.
|
|
933
|
-
- `zones`: A dictionary with up to two keys:
|
|
934
|
-
- **`system_context`**: Present if there is any system-level content. It contains:
|
|
935
|
-
- `tokens`: The total token count for the **entire combined system block** (e.g., `!@>system:\n...\n`).
|
|
936
|
-
- `content`: The full string content of the system block, showing exactly how all zones are merged.
|
|
937
|
-
- `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`.
|
|
938
|
-
- **`message_history`**: Present if there are messages in the branch. It contains:
|
|
939
|
-
- `tokens`: The total token count for the message history part of the prompt.
|
|
940
|
-
- `content`: The full string of the formatted message history.
|
|
941
|
-
- `message_count`: The number of messages included in the history.
|
|
942
|
-
|
|
943
|
-
- **Use Case:** Essential for debugging context issues, visualizing how different data zones contribute to the final prompt, and monitoring token consumption.
|
|
944
|
-
|
|
945
|
-
```python
|
|
946
|
-
import json
|
|
947
|
-
|
|
948
|
-
# Assuming 'discussion' is an LollmsDiscussion object with some data
|
|
949
|
-
discussion.system_prompt = "You are a helpful AI."
|
|
950
|
-
discussion.user_data_zone = "User is named Bob."
|
|
951
|
-
discussion.add_message(sender="user", content="Hello!")
|
|
952
|
-
discussion.add_message(sender="assistant", content="Hi Bob!")
|
|
953
|
-
|
|
954
|
-
status = discussion.get_context_status()
|
|
955
|
-
print(json.dumps(status, indent=2))
|
|
956
|
-
|
|
957
|
-
# Expected Output Structure:
|
|
958
|
-
# {
|
|
959
|
-
# "max_tokens": null,
|
|
960
|
-
# "current_tokens": 46,
|
|
961
|
-
# "zones": {
|
|
962
|
-
# "system_context": {
|
|
963
|
-
# "content": "You are a helpful AI.\n\n-- User Data Zone --\nUser is named Bob.",
|
|
964
|
-
# "tokens": 25,
|
|
965
|
-
# "breakdown": {
|
|
966
|
-
# "system_prompt": "You are a helpful AI.",
|
|
967
|
-
# "user_data_zone": "User is named Bob."
|
|
968
|
-
# }
|
|
969
|
-
# },
|
|
970
|
-
# "message_history": {
|
|
971
|
-
# "content": "!@>user:\nHello!\n!@>assistant:\nHi Bob!\n",
|
|
972
|
-
# "tokens": 21,
|
|
973
|
-
# "message_count": 2
|
|
974
|
-
# }
|
|
975
|
-
# }
|
|
976
|
-
# }
|
|
977
|
-
```
|
|
978
|
-
|
|
979
|
-
### Other Methods
|
|
980
|
-
- `add_message(sender, content, ...)`: Adds a new message.
|
|
981
|
-
- `export(format_type, ...)`: Exports the discussion to a specific format.
|
|
982
|
-
- `commit()`: Saves changes to the database (if DB-backed).
|
|
983
|
-
- `summarize_and_prune()`: Automatically handles context window limits.
|
|
984
|
-
- `count_discussion_tokens()`: Counts the tokens for a given format.
|
|
@@ -8,7 +8,7 @@ from lollms_client.lollms_utilities import PromptReshaper # Keep general utiliti
|
|
|
8
8
|
from lollms_client.lollms_mcp_binding import LollmsMCPBinding, LollmsMCPBindingManager
|
|
9
9
|
from lollms_client.lollms_llm_binding import LollmsLLMBindingManager
|
|
10
10
|
|
|
11
|
-
__version__ = "0.
|
|
11
|
+
__version__ = "0.31.0" # Updated version
|
|
12
12
|
|
|
13
13
|
# Optionally, you could define __all__ if you want to be explicit about exports
|
|
14
14
|
__all__ = [
|
|
@@ -11,6 +11,7 @@ from typing import Optional, Callable, List, Union, Dict
|
|
|
11
11
|
|
|
12
12
|
from ascii_colors import ASCIIColors, trace_exception
|
|
13
13
|
import pipmaster as pm
|
|
14
|
+
from lollms_client.lollms_utilities import ImageTokenizer
|
|
14
15
|
pm.ensure_packages(["ollama","pillow","tiktoken"])
|
|
15
16
|
|
|
16
17
|
|
|
@@ -468,6 +469,24 @@ class OllamaBinding(LollmsLLMBinding):
|
|
|
468
469
|
return -1
|
|
469
470
|
#return count_tokens_ollama(text, self.model_name, self.ollama_client)
|
|
470
471
|
return len(self.tokenize(text))
|
|
472
|
+
|
|
473
|
+
def count_image_tokens(self, image: str) -> int:
|
|
474
|
+
"""
|
|
475
|
+
Estimate the number of tokens for an image using ImageTokenizer based on self.model_name.
|
|
476
|
+
|
|
477
|
+
Args:
|
|
478
|
+
image (str): Image to count tokens from. Either base64 string, path to image file, or URL.
|
|
479
|
+
|
|
480
|
+
Returns:
|
|
481
|
+
int: Estimated number of tokens for the image. Returns -1 on error.
|
|
482
|
+
"""
|
|
483
|
+
try:
|
|
484
|
+
# Delegate token counting to ImageTokenizer
|
|
485
|
+
return ImageTokenizer(self.model_name).count_image_tokens(image)
|
|
486
|
+
except Exception as e:
|
|
487
|
+
ASCIIColors.warning(f"Could not estimate image tokens: {e}")
|
|
488
|
+
return -1
|
|
489
|
+
|
|
471
490
|
def embed(self, text: str, **kwargs) -> List[float]:
|
|
472
491
|
"""
|
|
473
492
|
Get embeddings for the input text using Ollama API.
|