lollms-client 0.28.0__tar.gz → 0.29.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.

Potentially problematic release.


This version of lollms-client might be problematic. Click here for more details.

Files changed (107) hide show
  1. lollms_client-0.29.1/PKG-INFO +963 -0
  2. lollms_client-0.29.1/README.md +932 -0
  3. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/text_gen.py +1 -1
  4. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/__init__.py +1 -1
  5. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/llm_bindings/llamacpp/__init__.py +1 -0
  6. {lollms_client-0.28.0/lollms_client/llm_bindings/lollms_chat → lollms_client-0.29.1/lollms_client/llm_bindings/lollms}/__init__.py +8 -7
  7. {lollms_client-0.28.0/lollms_client/llm_bindings/lollms → lollms_client-0.29.1/lollms_client/llm_bindings/lollms_webui}/__init__.py +2 -2
  8. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/lollms_core.py +157 -130
  9. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/lollms_discussion.py +343 -61
  10. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/lollms_personality.py +8 -0
  11. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/lollms_utilities.py +10 -2
  12. lollms_client-0.29.1/lollms_client.egg-info/PKG-INFO +963 -0
  13. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client.egg-info/SOURCES.txt +1 -1
  14. lollms_client-0.28.0/PKG-INFO +0 -604
  15. lollms_client-0.28.0/README.md +0 -573
  16. lollms_client-0.28.0/lollms_client.egg-info/PKG-INFO +0 -604
  17. {lollms_client-0.28.0 → lollms_client-0.29.1}/LICENSE +0 -0
  18. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/article_summary/article_summary.py +0 -0
  19. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/console_discussion/console_app.py +0 -0
  20. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/console_discussion.py +0 -0
  21. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/deep_analyze/deep_analyse.py +0 -0
  22. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/deep_analyze/deep_analyze_multiple_files.py +0 -0
  23. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/function_calling_with_local_custom_mcp.py +0 -0
  24. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/generate_a_benchmark_for_safe_store.py +0 -0
  25. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/generate_and_speak/generate_and_speak.py +0 -0
  26. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/generate_game_sfx/generate_game_fx.py +0 -0
  27. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/generate_text_with_multihop_rag_example.py +0 -0
  28. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/gradio_chat_app.py +0 -0
  29. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/gradio_lollms_chat.py +0 -0
  30. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/internet_search_with_rag.py +0 -0
  31. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/lollms_chat/calculator.py +0 -0
  32. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/lollms_chat/derivative.py +0 -0
  33. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/lollms_chat/test_openai_compatible_with_lollms_chat.py +0 -0
  34. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/lollms_discussions_test.py +0 -0
  35. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/mcp_examples/external_mcp.py +0 -0
  36. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/mcp_examples/local_mcp.py +0 -0
  37. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/mcp_examples/openai_mcp.py +0 -0
  38. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/mcp_examples/run_remote_mcp_example_v2.py +0 -0
  39. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/mcp_examples/run_standard_mcp_example.py +0 -0
  40. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/simple_text_gen_test.py +0 -0
  41. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/simple_text_gen_with_image_test.py +0 -0
  42. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/test_local_models/local_chat.py +0 -0
  43. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/text_2_audio.py +0 -0
  44. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/text_2_image.py +0 -0
  45. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/text_2_image_diffusers.py +0 -0
  46. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/text_and_image_2_audio.py +0 -0
  47. {lollms_client-0.28.0 → lollms_client-0.29.1}/examples/text_gen_system_prompt.py +0 -0
  48. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/llm_bindings/__init__.py +0 -0
  49. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/llm_bindings/azure_openai/__init__.py +0 -0
  50. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/llm_bindings/claude/__init__.py +0 -0
  51. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/llm_bindings/gemini/__init__.py +0 -0
  52. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/llm_bindings/grok/__init__.py +0 -0
  53. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/llm_bindings/groq/__init__.py +0 -0
  54. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/llm_bindings/hugging_face_inference_api/__init__.py +0 -0
  55. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/llm_bindings/litellm/__init__.py +0 -0
  56. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/llm_bindings/mistral/__init__.py +0 -0
  57. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/llm_bindings/ollama/__init__.py +0 -0
  58. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/llm_bindings/open_router/__init__.py +0 -0
  59. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/llm_bindings/openai/__init__.py +0 -0
  60. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/llm_bindings/openllm/__init__.py +0 -0
  61. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/llm_bindings/pythonllamacpp/__init__.py +0 -0
  62. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/llm_bindings/tensor_rt/__init__.py +0 -0
  63. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/llm_bindings/transformers/__init__.py +0 -0
  64. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/llm_bindings/vllm/__init__.py +0 -0
  65. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/lollms_config.py +0 -0
  66. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/lollms_js_analyzer.py +0 -0
  67. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/lollms_llm_binding.py +0 -0
  68. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/lollms_mcp_binding.py +0 -0
  69. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/lollms_python_analyzer.py +0 -0
  70. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/lollms_stt_binding.py +0 -0
  71. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/lollms_tti_binding.py +0 -0
  72. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/lollms_ttm_binding.py +0 -0
  73. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/lollms_tts_binding.py +0 -0
  74. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/lollms_ttv_binding.py +0 -0
  75. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/lollms_types.py +0 -0
  76. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/mcp_bindings/local_mcp/__init__.py +0 -0
  77. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/mcp_bindings/local_mcp/default_tools/file_writer/file_writer.py +0 -0
  78. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/mcp_bindings/local_mcp/default_tools/generate_image_from_prompt/generate_image_from_prompt.py +0 -0
  79. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/mcp_bindings/local_mcp/default_tools/internet_search/internet_search.py +0 -0
  80. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/mcp_bindings/local_mcp/default_tools/python_interpreter/python_interpreter.py +0 -0
  81. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/mcp_bindings/remote_mcp/__init__.py +0 -0
  82. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/mcp_bindings/standard_mcp/__init__.py +0 -0
  83. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/stt_bindings/__init__.py +0 -0
  84. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/stt_bindings/lollms/__init__.py +0 -0
  85. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/stt_bindings/whisper/__init__.py +0 -0
  86. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/stt_bindings/whispercpp/__init__.py +0 -0
  87. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/tti_bindings/__init__.py +0 -0
  88. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/tti_bindings/dalle/__init__.py +0 -0
  89. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/tti_bindings/diffusers/__init__.py +0 -0
  90. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/tti_bindings/gemini/__init__.py +0 -0
  91. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/tti_bindings/lollms/__init__.py +0 -0
  92. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/ttm_bindings/__init__.py +0 -0
  93. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/ttm_bindings/audiocraft/__init__.py +0 -0
  94. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/ttm_bindings/bark/__init__.py +0 -0
  95. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/ttm_bindings/lollms/__init__.py +0 -0
  96. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/tts_bindings/__init__.py +0 -0
  97. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/tts_bindings/bark/__init__.py +0 -0
  98. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/tts_bindings/lollms/__init__.py +0 -0
  99. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/tts_bindings/piper_tts/__init__.py +0 -0
  100. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/tts_bindings/xtts/__init__.py +0 -0
  101. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/ttv_bindings/__init__.py +0 -0
  102. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client/ttv_bindings/lollms/__init__.py +0 -0
  103. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client.egg-info/dependency_links.txt +0 -0
  104. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client.egg-info/requires.txt +0 -0
  105. {lollms_client-0.28.0 → lollms_client-0.29.1}/lollms_client.egg-info/top_level.txt +0 -0
  106. {lollms_client-0.28.0 → lollms_client-0.29.1}/pyproject.toml +0 -0
  107. {lollms_client-0.28.0 → lollms_client-0.29.1}/setup.cfg +0 -0
@@ -0,0 +1,963 @@
1
+ Metadata-Version: 2.4
2
+ Name: lollms_client
3
+ Version: 0.29.1
4
+ Summary: A client library for LoLLMs generate endpoint
5
+ Author-email: ParisNeo <parisneoai@gmail.com>
6
+ License: Apache Software License
7
+ Project-URL: Homepage, https://github.com/ParisNeo/lollms_client
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.8
10
+ Classifier: Programming Language :: Python :: 3.9
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: License :: OSI Approved :: Apache Software License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Intended Audience :: Science/Research
18
+ Requires-Python: >=3.7
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: requests
22
+ Requires-Dist: ascii-colors
23
+ Requires-Dist: pipmaster
24
+ Requires-Dist: pyyaml
25
+ Requires-Dist: tiktoken
26
+ Requires-Dist: pydantic
27
+ Requires-Dist: numpy
28
+ Requires-Dist: pillow
29
+ Requires-Dist: sqlalchemy
30
+ Dynamic: license-file
31
+
32
+ # LoLLMs Client Library
33
+
34
+ [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
35
+ [![PyPI version](https://badge.fury.io/py/lollms_client.svg)](https://badge.fury.io/py/lollms_client)
36
+ [![Python Versions](https://img.shields.io/pypi/pyversions/lollms_client.svg)](https://pypi.org/project/lollms_client/)
37
+ [![Downloads](https://static.pepy.tech/personalized-badge/lollms-client?period=total&units=international_system&left_color=grey&right_color=green&left_text=Downloads)](https://pepy.tech/project/lollms-client)
38
+ [![Documentation - Usage](https://img.shields.io/badge/docs-Usage%20Guide-brightgreen)](DOC_USE.md)
39
+ [![Documentation - Developer](https://img.shields.io/badge/docs-Developer%20Guide-blue)](DOC_DEV.md)
40
+ [![GitHub stars](https://img.shields.io/github/stars/ParisNeo/lollms_client.svg?style=social&label=Star&maxAge=2592000)](https://github.com/ParisNeo/lollms_client/stargazers/)
41
+ [![GitHub issues](https://img.shields.io/github/issues/ParisNeo/lollms_client.svg)](https://github.com/ParisNeo/lollms_client/issues)
42
+
43
+ **`lollms_client`** is a powerful and flexible Python library designed to simplify interactions with the **LoLLMs (Lord of Large Language Models)** ecosystem and various other Large Language Model (LLM) backends. It provides a unified API for text generation, multimodal operations (text-to-image, text-to-speech, etc.), and robust function calling through the Model Context Protocol (MCP).
44
+
45
+ Whether you're connecting to a remote LoLLMs server, an Ollama instance, the OpenAI API, or running models locally using GGUF (via `llama-cpp-python` or a managed `llama.cpp` server), Hugging Face Transformers, or vLLM, `lollms-client` offers a consistent and developer-friendly experience.
46
+
47
+ ## Key Features
48
+
49
+ * 🔌 **Versatile Binding System:** Seamlessly switch between different LLM backends (LoLLMs, Ollama, OpenAI, Llama.cpp, Transformers, vLLM, OpenLLM) without major code changes.
50
+ * 🗣️ **Multimodal Support:** Interact with models capable of processing images and generate various outputs like speech (TTS) and images (TTI).
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
+ * 🎭 **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
+ * 🚀 **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.
55
+ * 📝 **Advanced Structured Content Generation:** Reliably generate structured JSON output from natural language prompts using the `generate_structured_content` helper method.
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).
60
+ * ⚙️ **Configuration Management:** Flexible ways to configure bindings and generation parameters.
61
+ * 🧩 **Extensible:** Designed to easily incorporate new LLM backends and modality services, including custom MCP toolsets.
62
+ * 📝 **High-Level Operations:** Includes convenience methods for complex tasks like sequential summarization and deep text analysis directly within `LollmsClient`.
63
+
64
+ ## Installation
65
+
66
+ You can install `lollms_client` directly from PyPI:
67
+
68
+ ```bash
69
+ pip install lollms-client
70
+ ```
71
+
72
+ This will install the core library. Some bindings may require additional dependencies (e.g., `llama-cpp-python`, `torch`, `transformers`, `ollama`, `vllm`). The library attempts to manage these using `pipmaster`, but for complex dependencies (especially those requiring compilation like `llama-cpp-python` with GPU support), manual installation might be preferred.
73
+
74
+ ## Quick Start
75
+
76
+ Here's a very basic example of how to use `LollmsClient` to generate text with a LoLLMs server (ensure one is running at `http://localhost:9600`):
77
+
78
+ ```python
79
+ from lollms_client import LollmsClient, MSG_TYPE
80
+ from ascii_colors import ASCIIColors
81
+
82
+ # Callback for streaming output
83
+ def simple_streaming_callback(chunk: str, msg_type: MSG_TYPE, params=None, metadata=None) -> bool:
84
+ if msg_type == MSG_TYPE.MSG_TYPE_CHUNK:
85
+ print(chunk, end="", flush=True)
86
+ elif msg_type == MSG_TYPE.MSG_TYPE_EXCEPTION:
87
+ ASCIIColors.error(f"\nStreaming Error: {chunk}")
88
+ return True # True to continue streaming
89
+
90
+ try:
91
+ # Initialize client to connect to a LoLLMs server
92
+ # For other backends, change 'binding_name' and provide necessary parameters.
93
+ # See DOC_USE.md for detailed initialization examples.
94
+ lc = LollmsClient(
95
+ binding_name="lollms",
96
+ host_address="http://localhost:9600"
97
+ )
98
+
99
+ prompt = "Tell me a fun fact about space."
100
+ ASCIIColors.yellow(f"Prompt: {prompt}")
101
+
102
+ # Generate text with streaming
103
+ ASCIIColors.green("Streaming Response:")
104
+ response_text = lc.generate_text(
105
+ prompt,
106
+ n_predict=100,
107
+ stream=True,
108
+ streaming_callback=simple_streaming_callback
109
+ )
110
+ print("\n--- End of Stream ---")
111
+
112
+ # The 'response_text' variable will contain the full concatenated text
113
+ # if streaming_callback returns True throughout.
114
+ if isinstance(response_text, str):
115
+ ASCIIColors.cyan(f"\nFull streamed text collected: {response_text[:100]}...")
116
+ elif isinstance(response_text, dict) and "error" in response_text:
117
+ ASCIIColors.error(f"Error during generation: {response_text['error']}")
118
+
119
+ except ValueError as ve:
120
+ ASCIIColors.error(f"Initialization Error: {ve}")
121
+ ASCIIColors.info("Ensure a LoLLMs server is running or configure another binding.")
122
+ except ConnectionRefusedError:
123
+ ASCIIColors.error("Connection refused. Is the LoLLMs server running at http://localhost:9600?")
124
+ except Exception as e:
125
+ ASCIIColors.error(f"An unexpected error occurred: {e}")
126
+
127
+ ```
128
+
129
+ ### Advanced Structured Content Generation
130
+
131
+ The `generate_structured_content` method is a powerful utility for forcing an LLM's output into a specific JSON format. It's ideal for extracting information, getting consistent tool parameters, or any task requiring reliable, machine-readable output.
132
+
133
+ ```python
134
+ from lollms_client import LollmsClient
135
+ import json
136
+
137
+ lc = LollmsClient(binding_name="ollama", model_name="llama3")
138
+
139
+ text_block = "John Doe is a 34-year-old software engineer from New York. He loves hiking and Python programming."
140
+
141
+ # Define the exact JSON structure you want
142
+ output_template = {
143
+ "full_name": "string",
144
+ "age": "integer",
145
+ "profession": "string",
146
+ "city": "string",
147
+ "hobbies": ["list", "of", "strings"]
148
+ }
149
+
150
+ # Generate the structured data
151
+ extracted_data = lc.generate_structured_content(
152
+ prompt=f"Extract the relevant information from the following text:\n\n{text_block}",
153
+ output_format=output_template
154
+ )
155
+
156
+ if extracted_data:
157
+ print(json.dumps(extracted_data, indent=2))
158
+ # Expected output:
159
+ # {
160
+ # "full_name": "John Doe",
161
+ # "age": 34,
162
+ # "profession": "software engineer",
163
+ # "city": "New York",
164
+ # "hobbies": ["hiking", "Python programming"]
165
+ # }
166
+ ```
167
+
168
+ ### Putting It All Together: An Advanced Agentic Example
169
+
170
+ Let's create a **Python Coder Agent**. This agent will use a set of coding rules from a local file as its knowledge base and will be equipped with a tool to execute the code it writes. This demonstrates the synergy between `LollmsPersonality` (with `data_source` and `active_mcps`), `LollmsDiscussion`, and the MCP system.
171
+
172
+ #### Step 1: Create the Knowledge Base (`coding_rules.txt`)
173
+
174
+ Create a simple text file with the rules our agent must follow.
175
+
176
+ ```text
177
+ # File: coding_rules.txt
178
+
179
+ 1. All Python functions must include a Google-style docstring.
180
+ 2. Use type hints for all function parameters and return values.
181
+ 3. The main execution block should be protected by `if __name__ == "__main__":`.
182
+ 4. After defining a function, add a simple example of its usage inside the main block.
183
+ 5. Print the output of the example usage to the console.
184
+ ```
185
+
186
+ #### Step 2: The Main Script (`agent_example.py`)
187
+
188
+ This script will define the personality, initialize the client, and run the agent.
189
+
190
+ ```python
191
+ from pathlib import Path
192
+ from lollms_client import LollmsClient, LollmsPersonality, LollmsDiscussion, MSG_TYPE, trace_exception
193
+ from ascii_colors import ASCIIColors
194
+ import json
195
+
196
+ # A detailed callback to visualize the agent's process
197
+ def agent_callback(chunk: str, msg_type: MSG_TYPE, params: dict = None, **kwargs) -> bool:
198
+ if not params: params = {}
199
+
200
+ if msg_type == MSG_TYPE.MSG_TYPE_STEP:
201
+ ASCIIColors.yellow(f"\n>> Agent Step: {chunk}")
202
+ elif msg_type == MSG_TYPE.MSG_TYPE_STEP_START:
203
+ ASCIIColors.yellow(f"\n>> Agent Step Start: {chunk}")
204
+ elif msg_type == MSG_TYPE.MSG_TYPE_STEP_END:
205
+ result = params.get('result', '')
206
+ ASCIIColors.green(f"<< Agent Step End: {chunk} -> Result: {json.dumps(result)[:150]}...")
207
+ elif msg_type == MSG_TYPE.MSG_TYPE_THOUGHT_CONTENT:
208
+ ASCIIColors.magenta(f"🤔 Agent Thought: {chunk}")
209
+ elif msg_type == MSG_TYPE.MSG_TYPE_TOOL_CALL:
210
+ ASCIIColors.blue(f"🛠️ Agent Action: {chunk}")
211
+ elif msg_type == MSG_TYPE.MSG_TYPE_OBSERVATION:
212
+ ASCIIColors.cyan(f"👀 Agent Observation: {chunk}")
213
+ elif msg_type == MSG_TYPE.MSG_TYPE_CHUNK:
214
+ print(chunk, end="", flush=True) # Final answer stream
215
+ return True
216
+
217
+ try:
218
+ # --- 1. Load the knowledge base from the file ---
219
+ rules_path = Path("coding_rules.txt")
220
+ if not rules_path.exists():
221
+ raise FileNotFoundError("Please create the 'coding_rules.txt' file.")
222
+ coding_rules = rules_path.read_text()
223
+
224
+ # --- 2. Define the Coder Agent Personality ---
225
+ coder_personality = LollmsPersonality(
226
+ name="Python Coder Agent",
227
+ author="lollms-client",
228
+ category="Coding",
229
+ description="An agent that writes and executes Python code according to specific rules.",
230
+ system_prompt=(
231
+ "You are an expert Python programmer. Your task is to write clean, executable Python code based on the user's request. "
232
+ "You MUST strictly follow all rules provided in the 'Personality Static Data' section. "
233
+ "First, think about the plan. Then, use the `python_code_interpreter` tool to write and execute the code. "
234
+ "Finally, present the code and its output to the user."
235
+ ),
236
+ # A) Attach the static knowledge base
237
+ data_source=coding_rules,
238
+ # B) Equip the agent with a code execution tool
239
+ active_mcps=["python_code_interpreter"]
240
+ )
241
+
242
+ # --- 3. Initialize the Client and Discussion ---
243
+ lc = LollmsClient(
244
+ binding_name="ollama", # Or any capable model binding
245
+ model_name="codellama", # A code-specialized model is recommended
246
+ mcp_binding_name="local_mcp" # Enable the local tool execution engine
247
+ )
248
+ discussion = LollmsDiscussion.create_new(lollms_client=lc)
249
+
250
+ # --- 4. The User's Request ---
251
+ user_prompt = "Write a Python function that takes two numbers and returns their sum."
252
+
253
+ ASCIIColors.yellow(f"User Prompt: {user_prompt}")
254
+ print("\n" + "="*50 + "\nAgent is now running...\n" + "="*50)
255
+
256
+ # --- 5. Run the Agentic Chat Turn ---
257
+ response = discussion.chat(
258
+ user_message=user_prompt,
259
+ personality=coder_personality,
260
+ streaming_callback=agent_callback
261
+ )
262
+
263
+ print("\n\n" + "="*50 + "\nAgent finished.\n" + "="*50)
264
+
265
+ # --- 6. Inspect the results ---
266
+ ai_message = response['ai_message']
267
+ ASCIIColors.green("\n--- Final Answer from Agent ---")
268
+ print(ai_message.content)
269
+
270
+ ASCIIColors.magenta("\n--- Tool Calls Made ---")
271
+ print(json.dumps(ai_message.metadata.get("tool_calls", []), indent=2))
272
+
273
+ except Exception as e:
274
+ trace_exception(e)
275
+
276
+ ```
277
+
278
+ #### Step 3: What Happens Under the Hood
279
+
280
+ When you run `agent_example.py`, a sophisticated process unfolds:
281
+
282
+ 1. **Initialization:** The `LollmsDiscussion.chat()` method is called with the `coder_personality`.
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.
284
+ 3. **Tool Activation:** The method also sees `personality.active_mcps`. It enables the `python_code_interpreter` tool for this turn.
285
+ 4. **Context Assembly:** The `LollmsClient` assembles a rich prompt for the LLM that includes:
286
+ * The personality's `system_prompt`.
287
+ * The content of `coding_rules.txt` (from the data zones).
288
+ * The list of available tools (including `python_code_interpreter`).
289
+ * The user's request ("Write a function...").
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*.
291
+ 6. **Tool Execution:** The `local_mcp` binding receives the code and executes it in a secure local environment. It captures any output (`stdout`, `stderr`) and results.
292
+ 7. **Observation:** The execution results are sent back to the LLM as an "observation."
293
+ 8. **Final Synthesis:** The LLM now has the user's request, the rules, the code it wrote, and the code's output. It synthesizes all of this into a final, comprehensive answer for the user.
294
+
295
+ This example showcases how `lollms-client` allows you to build powerful, knowledgeable, and capable agents by simply composing personalities with data and tools.
296
+
297
+ ### Building Stateful Agents with Memory and Data Zones
298
+
299
+ The latest version of `LollmsDiscussion` introduces powerful features for creating agents that can remember information across conversations. This is achieved through structured data zones and a new `memorize()` method.
300
+
301
+ Let's build a "Personal Assistant" agent that learns about the user over time.
302
+
303
+ ```python
304
+ from lollms_client import LollmsClient, LollmsDataManager, LollmsDiscussion, MSG_TYPE
305
+ from ascii_colors import ASCIIColors
306
+ import json
307
+
308
+ # --- 1. Setup a persistent database for our discussion ---
309
+ db_manager = LollmsDataManager('sqlite:///my_assistant.db')
310
+ lc = LollmsClient(binding_name="ollama", model_name="llama3")
311
+
312
+ # Try to load an existing discussion or create a new one
313
+ discussion_id = "user_assistant_chat_1"
314
+ discussion = db_manager.get_discussion(lc, discussion_id)
315
+ if not discussion:
316
+ ASCIIColors.yellow("Creating a new discussion...")
317
+ discussion = LollmsDiscussion.create_new(
318
+ lollms_client=lc,
319
+ db_manager=db_manager,
320
+ id=discussion_id,
321
+ autosave=True # Important for persistence
322
+ )
323
+ # Let's preset some user data
324
+ discussion.user_data_zone = "User's Name: Alex\nUser's Goal: Learn about AI development."
325
+ discussion.commit()
326
+ else:
327
+ ASCIIColors.green("Loaded existing discussion.")
328
+
329
+
330
+ def run_chat_turn(prompt: str):
331
+ """Helper function to run a single chat turn and print details."""
332
+ ASCIIColors.cyan(f"\n> User: {prompt}")
333
+
334
+ # --- A. Check context status BEFORE the turn ---
335
+ ASCIIColors.magenta("\n--- Context Status (Before Generation) ---")
336
+ status = discussion.get_context_status()
337
+ print(f"Max Tokens: {status.get('max_tokens')}, Current Approx. Tokens: {status.get('current_tokens')}")
338
+ for zone, data in status.get('zones', {}).items():
339
+ print(f" - Zone: {zone}, Tokens: {data['tokens']}")
340
+ # print(f" Content: {data['content'][:80]}...") # Uncomment for more detail
341
+ print("------------------------------------------")
342
+
343
+ # --- B. Run the chat ---
344
+ ASCIIColors.green("\n< Assistant:")
345
+ response = discussion.chat(
346
+ user_message=prompt,
347
+ streaming_callback=lambda chunk, type, **k: print(chunk, end="", flush=True) if type==MSG_TYPE.MSG_TYPE_CHUNK else None
348
+ )
349
+ print() # Newline after stream
350
+
351
+ # --- C. Trigger memorization ---
352
+ ASCIIColors.yellow("\nTriggering memorization process...")
353
+ discussion.memorize()
354
+ discussion.commit() # Save the new memory to the DB
355
+ ASCIIColors.yellow("Memorization complete.")
356
+
357
+ # --- Run a few turns ---
358
+ run_chat_turn("Hi there! Can you recommend a good Python library for building web APIs?")
359
+ run_chat_turn("That sounds great. By the way, my favorite programming language is Rust, I find its safety features amazing.")
360
+ run_chat_turn("What was my favorite programming language again?")
361
+
362
+ # --- Final Inspection ---
363
+ ASCIIColors.magenta("\n--- Final Context Status ---")
364
+ status = discussion.get_context_status()
365
+ print(f"Max Tokens: {status.get('max_tokens')}, Current Approx. Tokens: {status.get('current_tokens')}")
366
+ for zone, data in status.get('zones', {}).items():
367
+ print(f" - Zone: {zone}, Tokens: {data['tokens']}")
368
+ print(f" Content: {data['content'][:150].replace(chr(10), ' ')}...")
369
+ print("------------------------------------------")
370
+
371
+ ```
372
+
373
+ #### How it Works:
374
+
375
+ 1. **Persistence:** The `LollmsDataManager` and `autosave=True` ensure that all changes to the discussion, including the data zones and memory, are saved to the `my_assistant.db` file. When you re-run the script, it loads the previous state.
376
+ 2. **`user_data_zone`:** We pre-filled this zone with basic user info. This context is provided to the AI in every turn.
377
+ 3. **`get_context_status()`:** Before each generation, we call this method to get a detailed breakdown of the prompt. This is excellent for debugging and understanding how the context window is being used.
378
+ 4. **`memorize()`:** After the user mentions their favorite language, `memorize()` is called. The LLM analyzes the last turn, identifies this new, important fact ("user's favorite language is Rust"), and appends it to the `discussion.memory` field.
379
+ 5. **Recall:** In the final turn, when asked to recall the favorite language, the AI has access to the `memory` zone and can correctly answer "Rust", even if that information had scrolled out of the recent conversation history. This demonstrates true long-term memory.
380
+
381
+ ## Documentation
382
+
383
+ For more in-depth information, please refer to:
384
+
385
+ * **[Usage Guide (DOC_USE.md)](DOC_USE.md):** Learn how to use `LollmsClient`, different bindings, modality features, function calling with MCP, and high-level operations.
386
+ * **[Developer Guide (DOC_DEV.md)](DOC_DEV.md):** Understand the architecture, how to create new bindings (LLM, modality, MCP), and contribute to the library.
387
+
388
+ ## Core Concepts
389
+
390
+ ```mermaid
391
+ graph LR
392
+ A[Your Application] --> LC[LollmsClient];
393
+
394
+ subgraph LollmsClient_Core
395
+ LC -- Manages --> LLB[LLM Binding];
396
+ LC -- Manages --> MCPB[MCP Binding];
397
+ LC -- Orchestrates --> MCP_Interaction[generate_with_mcp];
398
+ LC -- Provides --> HighLevelOps["High-Level Ops(summarize, deep_analyze etc.)"];
399
+ LC -- Provides Access To --> DM[DiscussionManager];
400
+ LC -- Provides Access To --> ModalityBindings[TTS, TTI, STT etc.];
401
+ end
402
+
403
+ subgraph LLM_Backends
404
+ LLB --> LollmsServer[LoLLMs Server];
405
+ LLB --> OllamaServer[Ollama];
406
+ LLB --> OpenAPIServer[OpenAI API];
407
+ LLB --> LocalGGUF["Local GGUF<br>(pythonllamacpp / llamacpp server)"];
408
+ LLB --> LocalHF["Local HuggingFace<br>(transformers / vLLM)"];
409
+ end
410
+
411
+ MCP_Interaction --> MCPB;
412
+ MCPB --> LocalTools["Local Python Tools<br>(via local_mcp)"];
413
+ MCPB --> RemoteTools["Remote MCP Tool Servers<br>(Future Potential)"];
414
+
415
+
416
+ ModalityBindings --> ModalityServices["Modality Services<br>(e.g., LoLLMs Server TTS/TTI, local Bark/XTTS)"];
417
+ ```
418
+
419
+ * **`LollmsClient`**: The central class for all interactions. It holds the currently active LLM binding, an optional MCP binding, and provides access to modality bindings and high-level operations.
420
+ * **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`.
421
+ * **🔧 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.
422
+ * **Modality Bindings**: Similar to LLM bindings, but for services like Text-to-Speech (`tts`), Text-to-Image (`tti`), etc.
423
+ * **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.
424
+ * **`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.
425
+
426
+ ## Examples
427
+
428
+ The `examples/` directory in this repository contains a rich set of scripts demonstrating various features:
429
+ * Basic text generation with different bindings.
430
+ * Streaming and non-streaming examples.
431
+ * Multimodal generation (text with images).
432
+ * Using built-in methods for summarization and Q&A.
433
+ * Implementing and using function calls with **`generate_with_mcp`** and the `local_mcp` binding (see `examples/function_calling_with_local_custom_mcp.py` and `examples/local_mcp.py`).
434
+ * Text-to-Speech and Text-to-Image generation.
435
+
436
+ Explore these examples to see `lollms-client` in action!
437
+
438
+ ## Using LoLLMs Client with Different Bindings
439
+
440
+ `lollms-client` supports a wide range of LLM backends through its binding system. This section provides practical examples of how to initialize `LollmsClient` for each of the major supported bindings.
441
+
442
+ ### A Note on Configuration
443
+
444
+ The recommended way to provide credentials and other binding-specific settings is through the `llm_binding_config` dictionary during `LollmsClient` initialization. While many bindings can fall back to reading environment variables (e.g., `OPENAI_API_KEY`), passing them explicitly in the config is clearer and less error-prone.
445
+
446
+ ```python
447
+ # General configuration pattern
448
+ lc = LollmsClient(
449
+ binding_name="your_binding_name",
450
+ model_name="a_model_name",
451
+ llm_binding_config={
452
+ "specific_api_key_param": "your_api_key_here",
453
+ "another_specific_param": "some_value"
454
+ }
455
+ )
456
+ ```
457
+
458
+ ---
459
+
460
+ ### 1. Local Bindings
461
+
462
+ These bindings run models directly on your local machine, giving you full control and privacy.
463
+
464
+ #### **Ollama**
465
+
466
+ The `ollama` binding connects to a running Ollama server instance on your machine or network.
467
+
468
+ **Prerequisites:**
469
+ * [Ollama installed and running](https://ollama.com/).
470
+ * Models pulled, e.g., `ollama pull llama3`.
471
+
472
+ **Usage:**
473
+
474
+ ```python
475
+ from lollms_client import LollmsClient
476
+
477
+ # Configuration for a local Ollama server
478
+ lc = LollmsClient(
479
+ binding_name="ollama",
480
+ model_name="llama3", # Or any other model you have pulled
481
+ host_address="http://localhost:11434" # Default Ollama address
482
+ )
483
+
484
+ # Now you can use lc.generate_text(), lc.chat(), etc.
485
+ response = lc.generate_text("Why is the sky blue?")
486
+ print(response)
487
+ ```
488
+
489
+ #### **PythonLlamaCpp (Local GGUF Models)**
490
+
491
+ The `pythonllamacpp` binding loads and runs GGUF model files directly using the powerful `llama-cpp-python` library. This is ideal for high-performance, local inference on CPU or GPU.
492
+
493
+ **Prerequisites:**
494
+ * A GGUF model file downloaded to your machine.
495
+ * `llama-cpp-python` installed. For GPU support, it must be compiled with the correct flags (e.g., `CMAKE_ARGS="-DLLAMA_CUBLAS=on" pip install llama-cpp-python`).
496
+
497
+ **Usage:**
498
+
499
+ ```python
500
+ from lollms_client import LollmsClient
501
+
502
+ # --- Configuration for Llama.cpp ---
503
+ # Path to your GGUF model file
504
+ MODEL_PATH = "/path/to/your/model.gguf"
505
+
506
+ # Binding-specific configuration
507
+ LLAMACPP_CONFIG = {
508
+ "n_gpu_layers": -1, # -1 for all layers to GPU, 0 for CPU
509
+ "n_ctx": 4096, # Context size
510
+ "seed": -1, # -1 for random seed
511
+ "chat_format": "chatml" # Or another format like 'llama-2'
512
+ }
513
+
514
+ try:
515
+ lc = LollmsClient(
516
+ binding_name="pythonllamacpp",
517
+ model_name=MODEL_PATH, # For this binding, model_name is the file path
518
+ llm_binding_config=LLAMACPP_CONFIG
519
+ )
520
+
521
+ response = lc.generate_text("Write a recipe for a great day.")
522
+ print(response)
523
+
524
+ except Exception as e:
525
+ print(f"Error initializing Llama.cpp binding: {e}")
526
+ print("Please ensure llama-cpp-python is installed and the model path is correct.")
527
+
528
+ ```
529
+
530
+ ---
531
+
532
+ ### 2. Cloud Service Bindings
533
+
534
+ These bindings connect to hosted LLM APIs from major providers.
535
+
536
+ #### **OpenAI**
537
+
538
+ Connects to the official OpenAI API to use models like GPT-4o, GPT-4, and GPT-3.5.
539
+
540
+ **Prerequisites:**
541
+ * An OpenAI API key.
542
+
543
+ **Usage:**
544
+
545
+ ```python
546
+ from lollms_client import LollmsClient
547
+
548
+ OPENAI_CONFIG = {
549
+ "service_key": "your_openai_api_key_here" # sk-...
550
+ }
551
+
552
+ lc = LollmsClient(
553
+ binding_name="openai",
554
+ model_name="gpt-4o",
555
+ llm_binding_config=OPENAI_CONFIG
556
+ )
557
+
558
+ response = lc.generate_text("What is the difference between AI and machine learning?")
559
+ print(response)
560
+ ```
561
+
562
+ #### **Google Gemini**
563
+
564
+ Connects to Google's Gemini family of models via the Google AI Studio API.
565
+
566
+ **Prerequisites:**
567
+ * A Google AI Studio API key.
568
+
569
+ **Usage:**
570
+
571
+ ```python
572
+ from lollms_client import LollmsClient
573
+
574
+ GEMINI_CONFIG = {
575
+ "service_key": "your_google_api_key_here"
576
+ }
577
+
578
+ lc = LollmsClient(
579
+ binding_name="gemini",
580
+ model_name="gemini-1.5-pro-latest",
581
+ llm_binding_config=GEMINI_CONFIG
582
+ )
583
+
584
+ response = lc.generate_text("Summarize the plot of 'Dune' in three sentences.")
585
+ print(response)
586
+ ```
587
+
588
+ #### **Anthropic Claude**
589
+
590
+ Connects to Anthropic's API to use the Claude family of models, including Claude 3.5 Sonnet, Opus, and Haiku.
591
+
592
+ **Prerequisites:**
593
+ * An Anthropic API key.
594
+
595
+ **Usage:**
596
+
597
+ ```python
598
+ from lollms_client import LollmsClient
599
+
600
+ CLAUDE_CONFIG = {
601
+ "service_key": "your_anthropic_api_key_here"
602
+ }
603
+
604
+ lc = LollmsClient(
605
+ binding_name="claude",
606
+ model_name="claude-3-5-sonnet-20240620",
607
+ llm_binding_config=CLAUDE_CONFIG
608
+ )
609
+
610
+ response = lc.generate_text("What are the core principles of constitutional AI?")
611
+ print(response)
612
+ ```
613
+
614
+ ---
615
+
616
+ ### 3. API Aggregator Bindings
617
+
618
+ These bindings connect to services that provide access to many different models through a single API.
619
+
620
+ #### **OpenRouter**
621
+
622
+ OpenRouter provides a unified, OpenAI-compatible interface to access models from dozens of providers (Google, Anthropic, Mistral, Groq, etc.) with one API key.
623
+
624
+ **Prerequisites:**
625
+ * An OpenRouter API key (starts with `sk-or-...`).
626
+
627
+ **Usage:**
628
+ Model names must be specified in the format `provider/model-name`.
629
+
630
+ ```python
631
+ from lollms_client import LollmsClient
632
+
633
+ OPENROUTER_CONFIG = {
634
+ "open_router_api_key": "your_openrouter_api_key_here"
635
+ }
636
+
637
+ # Example using a Claude model through OpenRouter
638
+ lc = LollmsClient(
639
+ binding_name="open_router",
640
+ model_name="anthropic/claude-3-haiku-20240307",
641
+ llm_binding_config=OPENROUTER_CONFIG
642
+ )
643
+
644
+ response = lc.generate_text("Explain what an API aggregator is, as if to a beginner.")
645
+ print(response)
646
+ ```
647
+
648
+ #### **Groq**
649
+
650
+ While Groq is a direct provider, it's famous as an aggregator of speed. It runs open-source models on custom LPU hardware for exceptionally fast inference.
651
+
652
+ **Prerequisites:**
653
+ * A Groq API key.
654
+
655
+ **Usage:**
656
+
657
+ ```python
658
+ from lollms_client import LollmsClient
659
+
660
+ GROQ_CONFIG = {
661
+ "groq_api_key": "your_groq_api_key_here"
662
+ }
663
+
664
+ lc = LollmsClient(
665
+ binding_name="groq",
666
+ model_name="llama3-8b-8192",
667
+ llm_binding_config=GROQ_CONFIG
668
+ )
669
+
670
+ response = lc.generate_text("Write a 3-line poem about incredible speed.")
671
+ print(response)
672
+ ```
673
+
674
+ #### **Hugging Face Inference API**
675
+
676
+ This connects to the serverless Hugging Face Inference API, allowing experimentation with thousands of open-source models without local hardware.
677
+
678
+ **Note:** This API can have "cold starts," so the first request might be slow.
679
+
680
+ **Prerequisites:**
681
+ * A Hugging Face User Access Token (starts with `hf_...`).
682
+
683
+ **Usage:**
684
+
685
+ ```python
686
+ from lollms_client import LollmsClient
687
+
688
+ HF_CONFIG = {
689
+ "hf_api_key": "your_hugging_face_token_here"
690
+ }
691
+
692
+ lc = LollmsClient(
693
+ binding_name="hugging_face_inference_api",
694
+ model_name="google/gemma-1.1-7b-it",
695
+ llm_binding_config=HF_CONFIG
696
+ )
697
+
698
+ response = lc.generate_text("Write a short story about a robot who discovers music.")
699
+ print(response)
700
+ ```
701
+
702
+ ### Sequential Summarization for Long Texts
703
+
704
+ 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.
705
+
706
+ ```python
707
+ from lollms_client import LollmsClient, MSG_TYPE, LollmsPersonality
708
+ from ascii_colors import ASCIIColors
709
+
710
+ # --- A very long text (imagine this is 10,000+ tokens) ---
711
+ long_text = """
712
+ The history of computing is a fascinating journey from mechanical contraptions to the powerful devices we use today.
713
+ It began with devices like the abacus, used for arithmetic tasks. In the 19th century, Charles Babbage conceived
714
+ the Analytical Engine, a mechanical computer that was never fully built but laid the groundwork for modern computing.
715
+ ...
716
+ (many, many paragraphs later)
717
+ ...
718
+ Today, quantum computing promises to revolutionize the field once again, tackling problems currently intractable
719
+ for even the most powerful supercomputers. Researchers are exploring qubits and quantum entanglement to create
720
+ machines that will redefine what is computationally possible, impacting fields from medicine to materials science.
721
+ """ * 50 # Simulate a very long text
722
+
723
+ # --- Callback to see the process in action ---
724
+ def summary_callback(chunk: str, msg_type: MSG_TYPE, params: dict = None, **kwargs):
725
+ if msg_type in [MSG_TYPE.MSG_TYPE_STEP_START, MSG_TYPE.MSG_TYPE_STEP_END]:
726
+ ASCIIColors.yellow(f">> {chunk}")
727
+ elif msg_type == MSG_TYPE.MSG_TYPE_STEP:
728
+ ASCIIColors.cyan(f" {chunk}")
729
+ return True
730
+
731
+ try:
732
+ lc = LollmsClient(binding_name="ollama", model_name="llama3")
733
+
734
+ # The contextual prompt guides the focus of the summary
735
+ context_prompt = "Summarize the text, focusing on the key technological milestones and their inventors."
736
+
737
+ ASCIIColors.blue("--- Starting Sequential Summarization ---")
738
+
739
+ final_summary = lc.summarize(
740
+ text_to_summarize=long_text,
741
+ contextual_prompt=context_prompt,
742
+ chunk_size_tokens=1000, # Adjust based on your model's context size
743
+ overlap_tokens=200,
744
+ streaming_callback=summary_callback,
745
+ temperature=0.1 # Good for factual summarization
746
+ )
747
+
748
+ ASCIIColors.blue("\n--- Final Comprehensive Summary ---")
749
+ ASCIIColors.green(final_summary)
750
+
751
+ except Exception as e:
752
+ print(f"An error occurred: {e}")
753
+ ```
754
+ ## Contributing
755
+
756
+ 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).
757
+
758
+ ## License
759
+
760
+ This project is licensed under the **Apache 2.0 License**. See the [LICENSE](LICENSE) file for details (assuming you have a LICENSE file, if not, state "Apache 2.0 License").
761
+
762
+ ## Changelog
763
+
764
+ 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
+ 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 part occupies.
926
+
927
+ - **Return Value:** A dictionary containing the `max_tokens`, `current_tokens`, and a `zones` dictionary with the content and token count for each component.
928
+ - **Use Case:** Essential for debugging context issues, understanding token usage, and visualizing how different data zones contribute to the final prompt.
929
+
930
+ ```python
931
+ import json
932
+
933
+ status = discussion.get_context_status()
934
+ print(json.dumps(status, indent=2))
935
+
936
+ # Expected Output Structure:
937
+ # {
938
+ # "max_tokens": 8192,
939
+ # "current_tokens": 521,
940
+ # "zones": {
941
+ # "system_prompt": {
942
+ # "content": "You are a helpful assistant.",
943
+ # "tokens": 12
944
+ # },
945
+ # "memory": {
946
+ # "content": "User's favorite color is blue.",
947
+ # "tokens": 15
948
+ # },
949
+ # "message_history": {
950
+ # "content": "!@>user:\nHi there!\n!@>assistant:\nHello! How can I help?\n",
951
+ # "tokens": 494,
952
+ # "message_count": 2
953
+ # }
954
+ # }
955
+ # }
956
+ ```
957
+
958
+ ### Other Methods
959
+ - `add_message(sender, content, ...)`: Adds a new message.
960
+ - `export(format_type, ...)`: Exports the discussion to a specific format.
961
+ - `commit()`: Saves changes to the database (if DB-backed).
962
+ - `summarize_and_prune()`: Automatically handles context window limits.
963
+ - `count_discussion_tokens()`: Counts the tokens for a given format.