lollms-client 1.5.5__tar.gz → 1.5.7__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.
Files changed (93) hide show
  1. {lollms_client-1.5.5/src/lollms_client.egg-info → lollms_client-1.5.7}/PKG-INFO +1 -1
  2. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/__init__.py +1 -1
  3. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/lollms/__init__.py +1 -1
  4. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/lollms_core.py +319 -152
  5. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/lollms_llm_binding.py +1 -1
  6. {lollms_client-1.5.5 → lollms_client-1.5.7/src/lollms_client.egg-info}/PKG-INFO +1 -1
  7. {lollms_client-1.5.5 → lollms_client-1.5.7}/LICENSE +0 -0
  8. {lollms_client-1.5.5 → lollms_client-1.5.7}/README.md +0 -0
  9. {lollms_client-1.5.5 → lollms_client-1.5.7}/pyproject.toml +0 -0
  10. {lollms_client-1.5.5 → lollms_client-1.5.7}/setup.cfg +0 -0
  11. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/assets/models_ctx_sizes.json +0 -0
  12. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/__init__.py +0 -0
  13. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/azure_openai/__init__.py +0 -0
  14. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/claude/__init__.py +0 -0
  15. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/gemini/__init__.py +0 -0
  16. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/grok/__init__.py +0 -0
  17. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/groq/__init__.py +0 -0
  18. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/hugging_face_inference_api/__init__.py +0 -0
  19. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/litellm/__init__.py +0 -0
  20. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/llamacpp/__init__.py +0 -0
  21. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/lollms_webui/__init__.py +0 -0
  22. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/mistral/__init__.py +0 -0
  23. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/novita_ai/__init__.py +0 -0
  24. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/ollama/__init__.py +0 -0
  25. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/open_router/__init__.py +0 -0
  26. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/openai/__init__.py +0 -0
  27. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/openllm/__init__.py +0 -0
  28. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/openwebui/__init__.py +0 -0
  29. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/perplexity/__init__.py +0 -0
  30. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/pythonllamacpp/__init__.py +0 -0
  31. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/tensor_rt/__init__.py +0 -0
  32. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/transformers/__init__.py +0 -0
  33. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/llm_bindings/vllm/__init__.py +0 -0
  34. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/lollms_agentic.py +0 -0
  35. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/lollms_config.py +0 -0
  36. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/lollms_discussion.py +0 -0
  37. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/lollms_js_analyzer.py +0 -0
  38. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/lollms_mcp_binding.py +0 -0
  39. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/lollms_mcp_security.py +0 -0
  40. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/lollms_personality.py +0 -0
  41. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/lollms_python_analyzer.py +0 -0
  42. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/lollms_stt_binding.py +0 -0
  43. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/lollms_tti_binding.py +0 -0
  44. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/lollms_ttm_binding.py +0 -0
  45. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/lollms_tts_binding.py +0 -0
  46. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/lollms_ttv_binding.py +0 -0
  47. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/lollms_types.py +0 -0
  48. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/lollms_utilities.py +0 -0
  49. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/mcp_bindings/local_mcp/__init__.py +0 -0
  50. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/mcp_bindings/local_mcp/default_tools/file_writer/file_writer.py +0 -0
  51. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/mcp_bindings/local_mcp/default_tools/generate_image_from_prompt/generate_image_from_prompt.py +0 -0
  52. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/mcp_bindings/local_mcp/default_tools/internet_search/internet_search.py +0 -0
  53. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/mcp_bindings/local_mcp/default_tools/python_interpreter/python_interpreter.py +0 -0
  54. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/mcp_bindings/remote_mcp/__init__.py +0 -0
  55. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/mcp_bindings/standard_mcp/__init__.py +0 -0
  56. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/stt_bindings/__init__.py +0 -0
  57. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/stt_bindings/lollms/__init__.py +0 -0
  58. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/stt_bindings/whisper/__init__.py +0 -0
  59. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/stt_bindings/whispercpp/__init__.py +0 -0
  60. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/tti_bindings/__init__.py +0 -0
  61. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/tti_bindings/diffusers/__init__.py +0 -0
  62. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/tti_bindings/gemini/__init__.py +0 -0
  63. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/tti_bindings/leonardo_ai/__init__.py +0 -0
  64. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/tti_bindings/lollms/__init__.py +0 -0
  65. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/tti_bindings/novita_ai/__init__.py +0 -0
  66. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/tti_bindings/openai/__init__.py +0 -0
  67. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/tti_bindings/stability_ai/__init__.py +0 -0
  68. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/ttm_bindings/__init__.py +0 -0
  69. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/ttm_bindings/audiocraft/__init__.py +0 -0
  70. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/ttm_bindings/beatoven_ai/__init__.py +0 -0
  71. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/ttm_bindings/lollms/__init__.py +0 -0
  72. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/ttm_bindings/replicate/__init__.py +0 -0
  73. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/ttm_bindings/stability_ai/__init__.py +0 -0
  74. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/ttm_bindings/topmediai/__init__.py +0 -0
  75. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/tts_bindings/__init__.py +0 -0
  76. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/tts_bindings/bark/__init__.py +0 -0
  77. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/tts_bindings/bark/server/install_bark.py +0 -0
  78. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/tts_bindings/bark/server/main.py +0 -0
  79. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/tts_bindings/lollms/__init__.py +0 -0
  80. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/tts_bindings/piper_tts/__init__.py +0 -0
  81. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/tts_bindings/piper_tts/server/install_piper.py +0 -0
  82. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/tts_bindings/piper_tts/server/main.py +0 -0
  83. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/tts_bindings/piper_tts/server/setup_voices.py +0 -0
  84. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/tts_bindings/xtts/__init__.py +0 -0
  85. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/tts_bindings/xtts/server/main.py +0 -0
  86. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/tts_bindings/xtts/server/setup_voices.py +0 -0
  87. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/ttv_bindings/__init__.py +0 -0
  88. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client/ttv_bindings/lollms/__init__.py +0 -0
  89. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client.egg-info/SOURCES.txt +0 -0
  90. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client.egg-info/dependency_links.txt +0 -0
  91. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client.egg-info/requires.txt +0 -0
  92. {lollms_client-1.5.5 → lollms_client-1.5.7}/src/lollms_client.egg-info/top_level.txt +0 -0
  93. {lollms_client-1.5.5 → lollms_client-1.5.7}/test/test_lollms_discussion.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lollms_client
3
- Version: 1.5.5
3
+ Version: 1.5.7
4
4
  Summary: A client library for LoLLMs generate endpoint
5
5
  Author-email: ParisNeo <parisneoai@gmail.com>
6
6
  License: Apache License
@@ -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__ = "1.5.5" # Updated version
11
+ __version__ = "1.5.7" # Updated version
12
12
 
13
13
  # Optionally, you could define __all__ if you want to be explicit about exports
14
14
  __all__ = [
@@ -232,7 +232,7 @@ class LollmsBinding(LollmsLLMBinding):
232
232
  chat_completion = self.client.chat.completions.create(**params)
233
233
  except Exception as ex:
234
234
  # exception for new openai models
235
- params["max_completion_tokens"]=params["max_tokens"]
235
+ params["max_completion_tokens"]=params.get("max_tokens") or params.get("max_completion_tokens") or self.default_ctx_size
236
236
  params["temperature"]=1
237
237
  try: del params["max_tokens"]
238
238
  except Exception: pass
@@ -1680,7 +1680,7 @@ Output the parameters as JSON: {{"tool_params": {{...}}}}"""
1680
1680
  raw_results = rag_fn(query=query, rag_top_k=rag_top_k, rag_min_similarity_percent=rag_min_similarity_percent)
1681
1681
  docs = [d for d in (raw_results.get("results", []) if isinstance(raw_results, dict) else raw_results or [])]
1682
1682
  tool_result = {"status": "success", "results": docs}
1683
- sources = [{"source": tool_name, "metadata": d.get("metadata", {}), "score": d.get("score", 0.0)} for d in docs]
1683
+ sources = [{"title":d["title"], "content":d["content"], "source": tool_name, "metadata": d.get("metadata", {}), "score": d.get("score", 0.0)} for d in docs]
1684
1684
  log_event(f"Retrieved {len(docs)} relevant documents", MSG_TYPE.MSG_TYPE_INFO)
1685
1685
  elif hasattr(self, "mcp") and "local_tools" not in tool_name:
1686
1686
  log_event(f"Executing MCP tool: {tool_name}", MSG_TYPE.MSG_TYPE_TOOL_CALL, meta={"tool_name": tool_name, "params": tool_params})
@@ -5736,186 +5736,353 @@ Provide the final aggregated answer in {output_format} format, directly addressi
5736
5736
  self,
5737
5737
  text_to_process: str,
5738
5738
  contextual_prompt: Optional[str] = None,
5739
- chunk_size_tokens: int|None = None,
5739
+ context_fill_percentage: float = 0.75,
5740
5740
  overlap_tokens: int = 0,
5741
+ expected_generation_tokens: int = 1500,
5741
5742
  streaming_callback: Optional[Callable] = None,
5743
+ return_scratchpad_only: bool = False,
5744
+ debug: bool = True,
5742
5745
  **kwargs
5743
5746
  ) -> str:
5744
- """
5745
- Summarizes a long text that may not fit into the model's context window.
5747
+ """Enhanced long context processing with Moby Dick literary analysis optimization."""
5746
5748
 
5747
- This method works in two stages:
5748
- 1. **Chunk & Summarize:** It breaks the text into overlapping chunks and summarizes each one individually.
5749
- 2. **Synthesize:** It then takes all the chunk summaries and performs a final summarization pass to create a single, coherent, and comprehensive summary.
5749
+ if debug:
5750
+ print(f"\n🔧 DEBUG: Starting processing with {len(text_to_process):,} characters")
5750
5751
 
5751
- Args:
5752
- text_to_process (str): The long text content to be summarized.
5753
- contextual_prompt (Optional[str], optional): A specific instruction to guide the summary's focus.
5754
- For example, "Summarize the text focusing on the financial implications."
5755
- Defaults to None.
5756
- chunk_size_tokens (int, optional): The number of tokens in each text chunk. This should be well
5757
- within the model's context limit to allow space for prompts.
5758
- Defaults to 1500.
5759
- overlap_tokens (int, optional): The number of tokens to overlap between chunks to ensure context
5760
- is not lost at the boundaries. Defaults to 250.
5761
- streaming_callback (Optional[Callable], optional): A callback function to receive real-time updates
5762
- on the process (e.g., which chunk is being processed).
5763
- It receives a message, a message type, and optional metadata.
5764
- Defaults to None.
5765
- **kwargs: Additional keyword arguments to be passed to the generation method (e.g., temperature, top_p).
5752
+ # Validate context fill percentage
5753
+ if not (0.1 <= context_fill_percentage <= 0.9):
5754
+ raise ValueError(f"context_fill_percentage must be between 0.1 and 0.9, got {context_fill_percentage}")
5766
5755
 
5767
- Returns:
5768
- str: The final, comprehensive summary of the text.
5769
- """
5770
- if not text_to_process and len(kwargs.get("images",[]))==0 and contextual_prompt is None:
5771
- return ""
5756
+ # Get context size
5757
+ try:
5758
+ context_size = self.llm.get_context_size() or 4096
5759
+ except:
5760
+ context_size = 4096
5761
+
5762
+ if debug:
5763
+ print(f"🔧 DEBUG: Context size: {context_size}, Fill %: {context_fill_percentage}")
5764
+
5765
+ # Handle empty input
5772
5766
  if not text_to_process:
5773
- text_to_process=""
5774
- tokens = []
5775
- else:
5776
- # Use the binding's tokenizer for accurate chunking
5777
- tokens = self.llm.tokenize(text_to_process)
5778
- if chunk_size_tokens is None:
5779
- chunk_size_tokens = self.llm.default_ctx_size//2
5780
-
5767
+ return ""
5768
+
5769
+ # Use word-based tokenization
5770
+ tokens = text_to_process.split()
5771
+ if debug:
5772
+ print(f"🔧 DEBUG: Tokenized into {len(tokens):,} word tokens")
5773
+
5774
+ # Dynamic token budget calculation
5775
+ def calculate_token_budgets(scratchpad_content: str = "", step_num: int = 0) -> dict:
5776
+ base_system_tokens = 250 # Increased for literary-specific prompts
5777
+ user_template_tokens = 300 # Increased for detailed instructions
5778
+ scratchpad_tokens = len(scratchpad_content.split()) * 1.3 if scratchpad_content else 0
5779
+
5780
+ used_tokens = base_system_tokens + user_template_tokens + scratchpad_tokens + expected_generation_tokens
5781
+ total_budget = int(context_size * context_fill_percentage)
5782
+ available_for_chunk = max(400, int(total_budget - used_tokens)) # Increased minimum for better context
5783
+
5784
+ budget_info = {
5785
+ "total_budget": total_budget,
5786
+ "chunk_budget": available_for_chunk,
5787
+ "efficiency_ratio": available_for_chunk / total_budget,
5788
+ "scratchpad_tokens": int(scratchpad_tokens),
5789
+ "used_tokens": int(used_tokens)
5790
+ }
5791
+
5792
+ if debug:
5793
+ print(f"🔧 DEBUG Step {step_num}: Budget = {available_for_chunk}/{total_budget} tokens, "
5794
+ f"Scratchpad = {int(scratchpad_tokens)} tokens")
5795
+
5796
+ return budget_info
5797
+
5798
+ # Initial budget calculation
5799
+ initial_budget = calculate_token_budgets()
5800
+ chunk_size_tokens = initial_budget["chunk_budget"]
5801
+
5802
+ if debug:
5803
+ print(f"🔧 DEBUG: Initial chunk size: {chunk_size_tokens} word tokens")
5804
+
5805
+ if streaming_callback:
5806
+ streaming_callback(
5807
+ f"Context Budget: {initial_budget['chunk_budget']:,}/{initial_budget['total_budget']:,} tokens "
5808
+ f"({initial_budget['efficiency_ratio']:.1%} efficiency)",
5809
+ MSG_TYPE.MSG_TYPE_STEP,
5810
+ {"budget_info": initial_budget}
5811
+ )
5812
+
5813
+ # Single pass for short content
5781
5814
  if len(tokens) <= chunk_size_tokens:
5815
+ if debug:
5816
+ print("🔧 DEBUG: Using single-pass processing")
5817
+
5782
5818
  if streaming_callback:
5783
- streaming_callback("Text is short enough for a single pass.", MSG_TYPE.MSG_TYPE_STEP, {"progress": 0})
5784
- system_prompt = ("You are a content processor expert.\n"
5785
- "You perform tasks on the content as requested by the user.\n\n"
5786
- "--- Content ---\n"
5787
- f"{text_to_process}\n\n"
5788
- "** Important **\n"
5789
- "Strictly adhere to the user prompt.\n"
5790
- "Do not add comments unless asked to do so.\n"
5791
- )
5792
- if "system_prompt" in kwargs:
5793
- system_prompt += "-- Extra instructions --\n"+ kwargs["system_prompt"] +"\n"
5794
- del kwargs["system_prompt"]
5795
- prompt_objective = contextual_prompt or "Provide a comprehensive summary of the content."
5796
- final_prompt = f"{prompt_objective}"
5797
-
5798
- processed_output = self.generate_text(final_prompt, system_prompt=system_prompt, **kwargs)
5799
-
5800
- if streaming_callback:
5801
- streaming_callback("Content processed.", MSG_TYPE.MSG_TYPE_STEP, {"progress": 100})
5802
-
5803
- return processed_output
5819
+ streaming_callback("Content fits in single pass", MSG_TYPE.MSG_TYPE_STEP, {})
5820
+
5821
+ # FIXED: Moby Dick-specific single-pass system prompt
5822
+ system_prompt = (
5823
+ "You are a literary analysis expert specializing in Herman Melville's works. "
5824
+ "Analyze the provided Moby Dick text with deep understanding that Melville's "
5825
+ "detailed realism, technical descriptions, and cultural documentation are "
5826
+ "integral literary techniques. Focus on themes, narrative methods, symbolism, "
5827
+ "and cultural commentary."
5828
+ )
5804
5829
 
5805
- # --- Stage 1: Chunking and Independent Summarization ---
5806
- chunks = []
5807
- step = chunk_size_tokens - overlap_tokens
5808
- for i in range(0, len(tokens), step):
5809
- chunk_tokens = tokens[i:i + chunk_size_tokens]
5810
- chunk_text = self.llm.detokenize(chunk_tokens)
5811
- chunks.append(chunk_text)
5830
+ prompt_objective = contextual_prompt or "Provide comprehensive Moby Dick literary analysis."
5831
+ final_prompt = f"{prompt_objective}\n\n--- Moby Dick Content ---\n{text_to_process}"
5832
+
5833
+ try:
5834
+ result = self.remove_thinking_blocks(self.llm.generate_text(final_prompt, system_prompt=system_prompt, **kwargs))
5835
+ if debug:
5836
+ print(f"🔧 DEBUG: Single-pass result: {len(result):,} characters")
5837
+ return result
5838
+ except Exception as e:
5839
+ if debug:
5840
+ print(f"🔧 DEBUG: Single-pass failed: {e}")
5841
+ return f"Error in single-pass processing: {e}"
5842
+
5843
+ # Multi-chunk processing with FIXED prompts
5844
+ if debug:
5845
+ print("🔧 DEBUG: Using multi-chunk processing with Moby Dick-optimized prompts")
5812
5846
 
5813
5847
  chunk_summaries = []
5814
-
5815
- # Total steps include each chunk plus the final synthesis step
5816
- total_steps = len(chunks) + 1
5817
-
5818
- # Define the prompt for summarizing each chunk
5819
- summarization_objective = contextual_prompt or "Summarize the key points of the following text excerpt."
5820
- system_prompt = ("You are a sequential document processing agent.\n"
5821
- "The process is done in two phases:\n"
5822
- "** Phase1 : **\n"
5823
- "Sequencially extracting information from the text chunks and adding them to the scratchpad.\n"
5824
- "** Phase2: **\n"
5825
- "Synthesizing a comprehensive Response using the scratchpad content given the objective formatting instructions if applicable.\n"
5826
- "We are now performing ** Phase 1 **, and we are processing chunk number {{chunk_id}}.\n"
5827
- "Your job is to extract information from the current chunk given previous chunks extracted information placed in scratchpad as well as the current chunk content.\n"
5828
- "Add the information to the scratchpad while strictly adhering to the Global objective extraction instructions:\n"
5829
- "-- Sequencial Scratchpad --\n"
5830
- "{{scratchpad}}\n"
5831
- "** Important **\n"
5832
- "Respond only with the extracted information from the current chunk without repeating things that are already in the scratchpad.\n"
5833
- "Strictly adhere to the Global objective content for the extraction phase.\n"
5834
- "Do not add comments.\n"
5835
- )
5836
- if "system_prompt" in kwargs:
5837
- system_prompt += "-- Extra instructions --\n"+ kwargs["system_prompt"] +"\n"
5838
- del kwargs["system_prompt"]
5839
- chunk_summary_prompt_template = f"--- Global objective ---\n{summarization_objective}\n\n--- Text Excerpt ---\n{{chunk_text}}"
5848
+ current_position = 0
5849
+ step_number = 1
5850
+
5851
+ while current_position < len(tokens):
5852
+ # Recalculate budget
5853
+ current_scratchpad = "\n\n---\n\n".join(chunk_summaries) if chunk_summaries else "[Empty]"
5854
+ current_budget = calculate_token_budgets(current_scratchpad, step_number)
5855
+ adaptive_chunk_size = max(400, current_budget["chunk_budget"]) # Increased minimum
5856
+
5857
+ # Extract chunk
5858
+ chunk_end = min(current_position + adaptive_chunk_size, len(tokens))
5859
+ chunk_tokens = tokens[current_position:chunk_end]
5860
+ chunk_text = " ".join(chunk_tokens)
5861
+
5862
+ if debug:
5863
+ print(f"\n🔧 DEBUG Step {step_number}: Processing chunk {current_position}:{chunk_end} "
5864
+ f"({len(chunk_tokens)} tokens, {len(chunk_text)} chars)")
5865
+
5866
+ # Progress calculation
5867
+ remaining_tokens = len(tokens) - current_position
5868
+ estimated_remaining_steps = max(1, remaining_tokens // adaptive_chunk_size)
5869
+ total_estimated_steps = step_number + estimated_remaining_steps - 1
5870
+ progress = (current_position / len(tokens)) * 90
5840
5871
 
5841
- for i, chunk in enumerate(chunks):
5842
- progress_before = (i / total_steps) * 100
5843
5872
  if streaming_callback:
5844
5873
  streaming_callback(
5845
- f"Processing chunk {i + 1} of {len(chunks)}...",
5846
- MSG_TYPE.MSG_TYPE_STEP_START,
5847
- {"id": f"chunk_{i+1}", "progress": progress_before}
5874
+ f"Processing chunk {step_number}/{total_estimated_steps} - "
5875
+ f"Budget: {adaptive_chunk_size:,} tokens",
5876
+ MSG_TYPE.MSG_TYPE_STEP_START,
5877
+ {"step": step_number, "progress": progress}
5848
5878
  )
5879
+
5849
5880
  try:
5850
- prompt = chunk_summary_prompt_template.format(chunk_text=chunk)
5851
- except Exception as ex:
5852
- ASCIIColors.warning(ex)
5853
- prompt = chunk_summary_prompt_template.replace("{chunk_text}", chunk)
5854
- processed_system_prompt = system_prompt.format(chunk_id=i,scratchpad="\n\n---\n\n".join(chunk_summaries))
5855
- try:
5856
- # Generate summary for the current chunk
5857
- chunk_summary = self.generate_text(prompt, system_prompt=processed_system_prompt, **kwargs)
5858
- chunk_summaries.append(chunk_summary)
5859
-
5860
- progress_after = ((i + 1) / total_steps) * 100
5881
+ # FIXED: Moby Dick-specific system prompt that prevents false filtering
5882
+ system_prompt = (
5883
+ f"You are analyzing Herman Melville's \"Moby Dick\" - a complex literary work where EVERY passage contains literary value.\n\n"
5884
+ f"**Critical Understanding:**\n"
5885
+ f"- Melville's detailed descriptions of whaling culture ARE literary techniques\n"
5886
+ f"- Technical passages reveal themes about knowledge, obsession, and human industry\n"
5887
+ f"- Social customs and maritime protocols reflect broader themes of hierarchy and civilization\n"
5888
+ f"- Even seemingly mundane details contribute to Melville's encyclopedic narrative style\n\n"
5889
+ f"**Current Status:** Step {step_number} of ~{total_estimated_steps} | Progress: {progress:.1f}%\n\n"
5890
+ f"**Your Task:**\n"
5891
+ f"Extract literary insights from this text chunk, focusing on:\n"
5892
+ f"1. **Themes** (obsession, knowledge, nature vs civilization, social hierarchy)\n"
5893
+ f"2. **Narrative Technique** (Melville's encyclopedic style, detailed realism)\n"
5894
+ f"3. **Cultural Commentary** (maritime society, American industry, social structures)\n"
5895
+ f"4. **Character Insights** (authority, dignity, social roles)\n"
5896
+ f"5. **Symbolic Elements** (ships, sea, whaling practices as metaphors)\n\n"
5897
+ f"**CRITICAL:** The scratchpad shows '{current_scratchpad[:20]}...' - if it shows '[Empty]', you are analyzing early content and everything you find is 'new' information. "
5898
+ f"Do NOT say '[No new information]' unless the chunk is literally empty or corrupted.\n\n"
5899
+ f"Be specific and extract concrete insights. Melville's detailed realism IS his literary technique."
5900
+ )
5901
+
5902
+ # FIXED: Moby Dick-specific user prompt with clear instructions
5903
+ summarization_objective = contextual_prompt or "Create comprehensive literary analysis of Moby-Dick focusing on themes, character development, narrative techniques, and symbolism"
5904
+
5905
+ # Determine scratchpad status for better context
5906
+ scratchpad_status = "The analysis is just beginning - this is among the first substantial content to be processed." if current_scratchpad == "[Empty]" else f"Building on existing analysis with {len(chunk_summaries)} sections already completed."
5907
+
5908
+ user_prompt = (
5909
+ f"--- Global Objective ---\n{summarization_objective}\n\n"
5910
+ f"--- Current Progress ---\n"
5911
+ f"Step {step_number} of ~{total_estimated_steps} | Progress: {progress:.1f}% | Token Budget: {adaptive_chunk_size:,}\n\n"
5912
+ f"--- Current Analysis State ---\n{scratchpad_status}\n\n"
5913
+ f"--- Existing Scratchpad Content ---\n{current_scratchpad}\n\n"
5914
+ f"--- New Text Chunk from Moby Dick ---\n{chunk_text}\n\n"
5915
+ f"--- Analysis Instructions ---\n"
5916
+ f"This is Melville's \"Moby Dick\" - extract literary insights from this passage. Consider:\n\n"
5917
+ f"• **What themes** does this passage develop? (obsession with knowledge, social hierarchy, maritime culture)\n"
5918
+ f"• **What narrative techniques** does Melville use? (detailed realism, encyclopedic style, technical precision)\n"
5919
+ f"• **What cultural commentary** is present? (whaling society, American industry, social protocols)\n"
5920
+ f"• **What character insights** emerge? (authority, dignity, social roles and expectations)\n"
5921
+ f"• **What symbolic elements** appear? (ships, maritime customs, hierarchical structures)\n\n"
5922
+ f"**Remember:** In Moby Dick, even technical descriptions serve literary purposes. Melville's detailed realism and cultural documentation ARE his narrative techniques.\n\n"
5923
+ f"Provide specific, concrete analysis with examples from the text. Extract insights that are not already captured in the scratchpad above."
5924
+ )
5925
+
5926
+ if debug:
5927
+ print(f"🔧 DEBUG: Sending {len(user_prompt)} char prompt to LLM")
5928
+ print(f"🔧 DEBUG: Scratchpad status: {scratchpad_status}")
5929
+
5930
+ chunk_summary = self.remove_thinking_blocks(self.llm.generate_text(user_prompt, system_prompt=system_prompt, **kwargs))
5931
+
5932
+ if debug:
5933
+ print(f"🔧 DEBUG: Received {len(chunk_summary)} char response")
5934
+ print(f"🔧 DEBUG: Response preview: {chunk_summary[:200]}...")
5935
+
5936
+ # FIXED: More intelligent content filtering specifically for literary analysis
5937
+ filter_out = False
5938
+
5939
+ # Check for explicit rejection signals
5940
+ if (chunk_summary.strip().startswith('[No new insights]') or
5941
+ chunk_summary.strip().startswith('[No new information]') or
5942
+ chunk_summary.strip().startswith('[No significant') or
5943
+ 'cannot provide' in chunk_summary.lower()[:100] or
5944
+ 'unable to analyze' in chunk_summary.lower()[:100]):
5945
+ filter_out = True
5946
+ filter_reason = "explicit rejection signal"
5947
+
5948
+ # Check for too short responses
5949
+ elif len(chunk_summary.strip()) < 50:
5950
+ filter_out = True
5951
+ filter_reason = "response too short"
5952
+
5953
+ # Check for error responses
5954
+ elif any(error_phrase in chunk_summary.lower()[:150] for error_phrase in [
5955
+ 'error', 'failed', 'cannot', 'unable', 'not possible', 'insufficient']):
5956
+ filter_out = True
5957
+ filter_reason = "error response detected"
5958
+
5959
+ else:
5960
+ filter_reason = "content accepted"
5961
+
5962
+ if not filter_out:
5963
+ chunk_summaries.append(chunk_summary.strip())
5964
+ content_added = True
5965
+ if debug:
5966
+ print(f"🔧 DEBUG: ✅ Content added to scratchpad (total sections: {len(chunk_summaries)})")
5967
+ else:
5968
+ content_added = False
5969
+ if debug:
5970
+ print(f"🔧 DEBUG: ❌ Content filtered out - {filter_reason}: {chunk_summary[:100]}...")
5971
+
5972
+ # Update progress
5861
5973
  if streaming_callback:
5974
+ updated_scratchpad = "\n\n---\n\n".join(chunk_summaries)
5862
5975
  streaming_callback(
5863
- f"Chunk {i + 1} processed. Progress: {progress_after:.0f}%",
5864
- MSG_TYPE.MSG_TYPE_STEP_END,
5865
- {"id": f"chunk_{i+1}", "output_snippet": chunk_summary[:100], "progress": progress_after}
5976
+ updated_scratchpad,
5977
+ MSG_TYPE.MSG_TYPE_SCRATCHPAD,
5978
+ {
5979
+ "step": step_number,
5980
+ "sections": len(chunk_summaries),
5981
+ "content_added": content_added,
5982
+ "filter_reason": filter_reason
5983
+ }
5866
5984
  )
5985
+
5986
+ progress_after = ((current_position + len(chunk_tokens)) / len(tokens)) * 90
5987
+ if streaming_callback:
5988
+ streaming_callback(
5989
+ f"Step {step_number} completed - {'Content added' if content_added else f'Filtered: {filter_reason}'}",
5990
+ MSG_TYPE.MSG_TYPE_STEP_END,
5991
+ {"progress": progress_after}
5992
+ )
5993
+
5867
5994
  except Exception as e:
5868
- trace_exception(e)
5995
+ error_msg = f"Step {step_number} failed: {str(e)}"
5996
+ if debug:
5997
+ print(f"🔧 DEBUG: ❌ {error_msg}")
5998
+ self.trace_exception(e)
5869
5999
  if streaming_callback:
5870
- streaming_callback(f"Failed to process chunk {i+1}: {e}", MSG_TYPE.MSG_TYPE_EXCEPTION)
5871
- # Still add a placeholder to not break the chain
5872
- chunk_summaries.append(f"[Error processing chunk {i+1}]")
6000
+ streaming_callback(error_msg, MSG_TYPE.MSG_TYPE_EXCEPTION)
6001
+ chunk_summaries.append(f"[Error in step {step_number}: {str(e)[:100]}]")
6002
+
6003
+ # Move to next chunk
6004
+ current_position += max(1, adaptive_chunk_size - overlap_tokens)
6005
+ step_number += 1
6006
+
6007
+ # Safety break
6008
+ if step_number > 50:
6009
+ if debug:
6010
+ print(f"🔧 DEBUG: Breaking after {step_number-1} steps for safety")
6011
+ break
6012
+
6013
+ if debug:
6014
+ print(f"\n🔧 DEBUG: Completed chunking. Total sections: {len(chunk_summaries)}")
6015
+
6016
+ # Return scratchpad if requested
6017
+ if return_scratchpad_only:
6018
+ final_scratchpad = "\n\n---\n\n".join(chunk_summaries)
6019
+ if streaming_callback:
6020
+ streaming_callback("Returning scratchpad only", MSG_TYPE.MSG_TYPE_STEP, {})
6021
+ return final_scratchpad.strip()
5873
6022
 
5874
- # --- Stage 2: Final Synthesis of All Chunk Summaries ---
5875
- progress_before_synthesis = (len(chunks) / total_steps) * 100
6023
+ # Final synthesis
5876
6024
  if streaming_callback:
5877
- streaming_callback(
5878
- "Processing the scratchpad content into a final version...",
5879
- MSG_TYPE.MSG_TYPE_STEP_START,
5880
- {"id": "final_synthesis", "progress": progress_before_synthesis}
5881
- )
6025
+ streaming_callback("Synthesizing final comprehensive analysis...", MSG_TYPE.MSG_TYPE_STEP_START, {"progress": 90})
5882
6026
 
5883
- combined_summaries = "\n\n---\n\n".join(chunk_summaries)
5884
-
5885
- # Define the prompt for the final synthesis
5886
- synthesis_objective = contextual_prompt or "Create a single, final, coherent, and comprehensive summary."
5887
- system_prompt = ("You are a sequential document processing agent.\n"
5888
- "The process is done in two phases:\n"
5889
- "** Phase1 : **\n"
5890
- "Sequencially extracting information from the text chunks and adding them to the scratchpad.\n"
5891
- "** Phase2: **\n"
5892
- "Synthesizing a comprehensive Response using the scratchpad content given the objective formatting instructions if applicable.\n"
5893
- "\n"
5894
- "We are now performing ** Phase 2 **.\n"
5895
- "Your job is to use the extracted information to fulfill the user prompt objectives.\n"
5896
- "Make sure you respect the user formatting if provided and if not, then use markdown output format."
5897
- "-- Sequencial Scratchpad --\n"
5898
- f"{combined_summaries}\n"
5899
- "** Important **\n"
5900
- "Respond only with the requested task without extra comments unless told to.\n"
5901
- "Strictly adhere to the Global objective content for the extraction phase.\n"
5902
- "Do not add comments.\n"
5903
- )
5904
- final_synthesis_prompt = (
5905
- f"--- Global objective ---\n{synthesis_objective}\n\n"
5906
- "--- Final Response ---"
6027
+ if not chunk_summaries:
6028
+ error_msg = "No content was successfully processed. The text may not contain recognizable literary elements, or there may be an issue with the processing."
6029
+ if debug:
6030
+ print(f"🔧 DEBUG: {error_msg}")
6031
+ return error_msg
6032
+
6033
+ combined_scratchpad = "\n\n---\n\n".join(chunk_summaries)
6034
+ synthesis_objective = contextual_prompt or "Create comprehensive literary analysis of Moby-Dick."
6035
+
6036
+ if debug:
6037
+ print(f"🔧 DEBUG: Synthesizing from {len(combined_scratchpad):,} char scratchpad with {len(chunk_summaries)} sections")
6038
+
6039
+ # FIXED: Moby Dick-specific synthesis prompts
6040
+ synthesis_system_prompt = (
6041
+ "You are a literary analysis expert creating a final comprehensive analysis of Herman Melville's Moby Dick.\n"
6042
+ "Synthesize all the insights from the analysis sections into a coherent, scholarly response.\n"
6043
+ "Create clear sections with markdown headers, eliminate redundancy, and provide a thorough analysis.\n"
6044
+ "Focus on Melville's major themes, narrative techniques, cultural commentary, and symbolic elements.\n"
6045
+ "Use specific examples from the text and maintain academic rigor throughout."
5907
6046
  )
5908
6047
 
5909
- final_answer = self.generate_text(final_synthesis_prompt, system_prompt=system_prompt, **kwargs)
5910
-
5911
- if streaming_callback:
5912
- streaming_callback(
5913
- "Final summary synthesized.",
5914
- MSG_TYPE.MSG_TYPE_STEP_END,
5915
- {"id": "final_synthesis", "progress": 100}
5916
- )
6048
+ synthesis_user_prompt = (
6049
+ f"--- Analysis Objective ---\n{synthesis_objective}\n\n"
6050
+ f"--- Processing Summary ---\n"
6051
+ f"Successfully analyzed {len(chunk_summaries)} sections of Moby Dick through incremental literary analysis.\n"
6052
+ f"Total scratchpad content: {len(combined_scratchpad):,} characters of literary insights.\n\n"
6053
+ f"--- Collected Literary Analysis Sections ---\n{combined_scratchpad}\n\n"
6054
+ f"--- Final Synthesis Task ---\n"
6055
+ f"Create a comprehensive, well-structured literary analysis of Moby Dick using ALL the insights above. "
6056
+ f"Organize into clear sections with markdown headers (## Theme Analysis, ## Narrative Techniques, ## Cultural Commentary, ## Symbolism, etc.). "
6057
+ f"Eliminate redundancy and create a coherent, scholarly analysis that demonstrates understanding of Melville's complex literary achievement. "
6058
+ f"Include specific textual examples and maintain academic depth throughout."
6059
+ )
6060
+
6061
+ try:
6062
+ final_answer = self.remove_thinking_blocks(self.llm.generate_text(synthesis_user_prompt, system_prompt=synthesis_system_prompt, **kwargs))
5917
6063
 
5918
- return final_answer.strip()
6064
+ if debug:
6065
+ print(f"🔧 DEBUG: Final analysis: {len(final_answer):,} characters")
6066
+
6067
+ if streaming_callback:
6068
+ streaming_callback(f"Final synthesis completed - {len(final_answer):,} characters generated", MSG_TYPE.MSG_TYPE_STEP_END, {"progress": 100})
6069
+
6070
+ return final_answer.strip()
6071
+
6072
+ except Exception as e:
6073
+ error_msg = f"Synthesis failed: {str(e)}. Returning organized scratchpad content."
6074
+ if debug:
6075
+ print(f"🔧 DEBUG: ❌ {error_msg}")
6076
+
6077
+ # Return organized scratchpad as fallback
6078
+ organized_scratchpad = (
6079
+ f"# Literary Analysis of Moby Dick\n\n"
6080
+ f"*Note: Synthesis process encountered issues, presenting organized analysis sections:*\n\n"
6081
+ f"## Analysis Sections\n\n"
6082
+ f"{combined_scratchpad}"
6083
+ )
6084
+ return organized_scratchpad
6085
+
5919
6086
 
5920
6087
  def chunk_text(text, tokenizer, detokenizer, chunk_size, overlap, use_separators=True):
5921
6088
  """
@@ -197,7 +197,7 @@ class LollmsLLMBinding(ABC):
197
197
  """
198
198
  pass
199
199
 
200
- def get_ctx_size(self, model_name: Optional[str] = None) -> Optional[int]:
200
+ def get_ctx_size(self, model_name: Optional[str|None] = None) -> Optional[int]:
201
201
  """
202
202
  Retrieves context size for a model from a hardcoded list.
203
203
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lollms_client
3
- Version: 1.5.5
3
+ Version: 1.5.7
4
4
  Summary: A client library for LoLLMs generate endpoint
5
5
  Author-email: ParisNeo <parisneoai@gmail.com>
6
6
  License: Apache License
File without changes
File without changes
File without changes