PraisonAI 2.0.73__tar.gz → 2.0.75__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 PraisonAI might be problematic. Click here for more details.

Files changed (89) hide show
  1. {praisonai-2.0.73 → praisonai-2.0.75}/PKG-INFO +1 -1
  2. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/cli.py +12 -1
  3. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/deploy.py +1 -1
  4. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/setup/setup_conda_env.sh +1 -1
  5. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/train.py +31 -23
  6. praisonai-2.0.75/praisonai/train_vision.py +234 -0
  7. {praisonai-2.0.73 → praisonai-2.0.75}/pyproject.toml +2 -2
  8. {praisonai-2.0.73 → praisonai-2.0.75}/LICENSE +0 -0
  9. {praisonai-2.0.73 → praisonai-2.0.75}/README.md +0 -0
  10. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/__init__.py +0 -0
  11. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/__main__.py +0 -0
  12. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/agents_generator.py +0 -0
  13. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/api/call.py +0 -0
  14. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/auto.py +0 -0
  15. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/chainlit_ui.py +0 -0
  16. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/inbuilt_tools/__init__.py +0 -0
  17. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/inbuilt_tools/autogen_tools.py +0 -0
  18. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/inc/__init__.py +0 -0
  19. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/inc/config.py +0 -0
  20. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/inc/models.py +0 -0
  21. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/public/android-chrome-192x192.png +0 -0
  22. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/public/android-chrome-512x512.png +0 -0
  23. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/public/apple-touch-icon.png +0 -0
  24. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/public/fantasy.svg +0 -0
  25. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/public/favicon-16x16.png +0 -0
  26. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/public/favicon-32x32.png +0 -0
  27. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/public/favicon.ico +0 -0
  28. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/public/game.svg +0 -0
  29. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/public/logo_dark.png +0 -0
  30. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/public/logo_light.png +0 -0
  31. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/public/movie.svg +0 -0
  32. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/public/praison-ai-agents-architecture-dark.png +0 -0
  33. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/public/praison-ai-agents-architecture.png +0 -0
  34. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/public/thriller.svg +0 -0
  35. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/setup/__init__.py +0 -0
  36. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/setup/build.py +0 -0
  37. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/setup/config.yaml +0 -0
  38. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/setup/post_install.py +0 -0
  39. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/setup/setup_conda_env.py +0 -0
  40. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/setup.py +0 -0
  41. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/test.py +0 -0
  42. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/README.md +0 -0
  43. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/agents.py +0 -0
  44. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/callbacks.py +0 -0
  45. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/chat.py +0 -0
  46. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/code.py +0 -0
  47. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/colab.py +0 -0
  48. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/colab_chainlit.py +0 -0
  49. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/components/aicoder.py +0 -0
  50. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/.chainlit/config.toml +0 -0
  51. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/.chainlit/translations/bn.json +0 -0
  52. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/.chainlit/translations/en-US.json +0 -0
  53. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/.chainlit/translations/gu.json +0 -0
  54. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/.chainlit/translations/he-IL.json +0 -0
  55. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/.chainlit/translations/hi.json +0 -0
  56. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/.chainlit/translations/kn.json +0 -0
  57. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/.chainlit/translations/ml.json +0 -0
  58. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/.chainlit/translations/mr.json +0 -0
  59. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/.chainlit/translations/ta.json +0 -0
  60. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/.chainlit/translations/te.json +0 -0
  61. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/.chainlit/translations/zh-CN.json +0 -0
  62. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/chainlit.md +0 -0
  63. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/translations/bn.json +0 -0
  64. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/translations/en-US.json +0 -0
  65. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/translations/gu.json +0 -0
  66. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/translations/he-IL.json +0 -0
  67. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/translations/hi.json +0 -0
  68. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/translations/kn.json +0 -0
  69. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/translations/ml.json +0 -0
  70. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/translations/mr.json +0 -0
  71. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/translations/ta.json +0 -0
  72. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/translations/te.json +0 -0
  73. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/config/translations/zh-CN.json +0 -0
  74. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/context.py +0 -0
  75. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/db.py +0 -0
  76. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/public/fantasy.svg +0 -0
  77. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/public/game.svg +0 -0
  78. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/public/logo_dark.png +0 -0
  79. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/public/logo_light.png +0 -0
  80. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/public/movie.svg +0 -0
  81. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/public/praison.css +0 -0
  82. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/public/thriller.svg +0 -0
  83. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/realtime.py +0 -0
  84. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/realtimeclient/__init__.py +0 -0
  85. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/realtimeclient/realtimedocs.txt +0 -0
  86. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/realtimeclient/tools.py +0 -0
  87. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/sql_alchemy.py +0 -0
  88. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/ui/tools.md +0 -0
  89. {praisonai-2.0.73 → praisonai-2.0.75}/praisonai/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: PraisonAI
3
- Version: 2.0.73
3
+ Version: 2.0.75
4
4
  Summary: PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human-agent collaboration.
5
5
  Author: Mervin Praison
6
6
  Requires-Python: >=3.10,<3.13
@@ -240,7 +240,18 @@ class PraisonAI:
240
240
  print("All packages installed.")
241
241
 
242
242
  train_args = sys.argv[2:] # Get all arguments after 'train'
243
- train_script_path = os.path.join(package_root, 'train.py')
243
+
244
+ # Check if this is a vision model - handle all case variations
245
+ model_name = config.get("model_name", "").lower()
246
+ is_vision_model = any(x in model_name for x in ["-vl-", "-vl", "vl-", "-vision-", "-vision", "vision-", "visionmodel"])
247
+
248
+ # Choose appropriate training script
249
+ if is_vision_model:
250
+ train_script_path = os.path.join(package_root, 'train_vision.py')
251
+ print("Using vision training script for VL model...")
252
+ else:
253
+ train_script_path = os.path.join(package_root, 'train.py')
254
+ print("Using standard training script...")
244
255
 
245
256
  # Set environment variables
246
257
  env = os.environ.copy()
@@ -56,7 +56,7 @@ class CloudDeployer:
56
56
  file.write("FROM python:3.11-slim\n")
57
57
  file.write("WORKDIR /app\n")
58
58
  file.write("COPY . .\n")
59
- file.write("RUN pip install flask praisonai==2.0.73 gunicorn markdown\n")
59
+ file.write("RUN pip install flask praisonai==2.0.75 gunicorn markdown\n")
60
60
  file.write("EXPOSE 8080\n")
61
61
  file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
62
62
 
@@ -96,7 +96,7 @@ PIP_FULL_PATH=$(conda run -n "$ENV_NAME" which pip)
96
96
  # Install other packages using pip
97
97
  $PIP_FULL_PATH install --upgrade pip
98
98
  $PIP_FULL_PATH install "xformers==0.0.26.post1"
99
- $PIP_FULL_PATH install "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git@038e6d4c8d40207a87297ab3aaf787c19b1006d1"
99
+ $PIP_FULL_PATH install "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git@53a773e4fbc53a1d96c7ba107e5fe75dab07027b"
100
100
  $PIP_FULL_PATH install --no-deps "trl<0.9.0" peft accelerate bitsandbytes
101
101
  $PIP_FULL_PATH install unsloth_zoo
102
102
  $PIP_FULL_PATH install cut_cross_entropy
@@ -216,25 +216,29 @@ class TrainModel:
216
216
  raw_dataset = self.load_datasets()
217
217
  tokenized_dataset = self.tokenize_dataset(raw_dataset)
218
218
  print("DEBUG: Dataset tokenization complete.")
219
- training_args = TrainingArguments(
220
- per_device_train_batch_size=self.config.get("per_device_train_batch_size", 2),
221
- gradient_accumulation_steps=self.config.get("gradient_accumulation_steps", 2),
222
- warmup_steps=self.config.get("warmup_steps", 50),
223
- max_steps=self.config.get("max_steps", 2800),
224
- learning_rate=self.config.get("learning_rate", 2e-4),
225
- fp16=self.config.get("fp16", not is_bfloat16_supported()),
226
- bf16=self.config.get("bf16", is_bfloat16_supported()),
227
- logging_steps=self.config.get("logging_steps", 15),
228
- optim=self.config.get("optim", "adamw_8bit"),
229
- weight_decay=self.config.get("weight_decay", 0.01),
230
- lr_scheduler_type=self.config.get("lr_scheduler_type", "linear"),
231
- seed=self.config.get("seed", 3407),
232
- output_dir=self.config.get("output_dir", "outputs"),
233
- report_to="none" if not os.getenv("PRAISON_WANDB") else "wandb",
234
- save_steps=self.config.get("save_steps", 100) if os.getenv("PRAISON_WANDB") else None,
235
- run_name=os.getenv("PRAISON_WANDB_RUN_NAME", "praisonai-train") if os.getenv("PRAISON_WANDB") else None,
236
- remove_unused_columns=self.config.get("remove_unused_columns", False),
237
- )
219
+ # Build the training arguments parameters dynamically
220
+ ta_params = {
221
+ "per_device_train_batch_size": self.config.get("per_device_train_batch_size", 2),
222
+ "gradient_accumulation_steps": self.config.get("gradient_accumulation_steps", 2),
223
+ "warmup_steps": self.config.get("warmup_steps", 50),
224
+ "max_steps": self.config.get("max_steps", 2800),
225
+ "learning_rate": self.config.get("learning_rate", 2e-4),
226
+ "fp16": self.config.get("fp16", not is_bfloat16_supported()),
227
+ "bf16": self.config.get("bf16", is_bfloat16_supported()),
228
+ "logging_steps": self.config.get("logging_steps", 15),
229
+ "optim": self.config.get("optim", "adamw_8bit"),
230
+ "weight_decay": self.config.get("weight_decay", 0.01),
231
+ "lr_scheduler_type": self.config.get("lr_scheduler_type", "linear"),
232
+ "seed": self.config.get("seed", 3407),
233
+ "output_dir": self.config.get("output_dir", "outputs"),
234
+ "report_to": "none" if not os.getenv("PRAISON_WANDB") else "wandb",
235
+ "remove_unused_columns": self.config.get("remove_unused_columns", False)
236
+ }
237
+ if os.getenv("PRAISON_WANDB"):
238
+ ta_params["save_steps"] = self.config.get("save_steps", 100)
239
+ ta_params["run_name"] = os.getenv("PRAISON_WANDB_RUN_NAME", "praisonai-train")
240
+
241
+ training_args = TrainingArguments(**ta_params)
238
242
  # Since the dataset is pre-tokenized, we supply a dummy dataset_text_field.
239
243
  trainer = SFTTrainer(
240
244
  model=self.model,
@@ -425,12 +429,16 @@ class TrainModel:
425
429
  "template": """{{- if .System }}{{ .System }}{{ end }}
426
430
  {{- range $i, $_ := .Messages }}
427
431
  {{- $last := eq (len (slice $.Messages $i)) 1}}
428
- {{- if eq .Role "user" }}<|User|>{{ .Content }}
429
- {{- else if eq .Role "assistant" }}<|Assistant|>{{ .Content }}{{- if not $last }}<|end▁of▁sentence|>{{- end }}
432
+ {{- if eq .Role "user" }}
433
+ {{ .Content }}
434
+ {{- else if eq .Role "assistant" }}
435
+ {{ .Content }}{{- if not $last }}
436
+ {{- end }}
430
437
  {{- end }}
431
- {{- if and $last (ne .Role "assistant") }}<|Assistant|>{{- end }}
438
+ {{- if and $last (ne .Role "assistant") }}
439
+ {{ end }}
432
440
  {{- end }}""",
433
- "stop_tokens": ["<|begin▁of▁sentence|>", "<|end▁of▁sentence|>", "<|User|>", "<|Assistant|>"]
441
+ "stop_tokens": ["", "", "", ""]
434
442
  },
435
443
  "llava": {
436
444
  "template": """{{- if .Suffix }}<|fim_prefix|>{{ .Prompt }}<|fim_suffix|>{{ .Suffix }}<|fim_middle|>
@@ -0,0 +1,234 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ This script finetunes a vision language model using Unsloth's fast training framework.
5
+ It supports vision tasks by converting raw image-caption samples into a conversation format,
6
+ adding vision-specific LoRA adapters, and training using TRL's SFTTrainer with UnslothVisionDataCollator.
7
+ """
8
+
9
+ import os
10
+ import sys
11
+ import yaml
12
+ import torch
13
+ import shutil
14
+ import subprocess
15
+
16
+ from datasets import load_dataset, concatenate_datasets
17
+ from unsloth import FastVisionModel, is_bf16_supported
18
+ from unsloth.trainer import UnslothVisionDataCollator
19
+ from trl import SFTTrainer, SFTConfig
20
+
21
+
22
+ class TrainVisionModel:
23
+ def __init__(self, config_path="config.yaml"):
24
+ self.load_config(config_path)
25
+ self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
26
+ self.model = None
27
+ self.hf_tokenizer = None # The underlying tokenizer
28
+
29
+ def load_config(self, path):
30
+ with open(path, "r") as file:
31
+ self.config = yaml.safe_load(file)
32
+ print("DEBUG: Loaded config:", self.config)
33
+
34
+ def print_system_info(self):
35
+ print("DEBUG: PyTorch version:", torch.__version__)
36
+ print("DEBUG: CUDA version:", torch.version.cuda)
37
+ if torch.cuda.is_available():
38
+ print("DEBUG: CUDA Device Capability:", torch.cuda.get_device_capability())
39
+ else:
40
+ print("DEBUG: CUDA is not available")
41
+ print("DEBUG: Python Version:", sys.version)
42
+ print("DEBUG: Python Path:", sys.executable)
43
+
44
+ def check_gpu(self):
45
+ gpu_stats = torch.cuda.get_device_properties(0)
46
+ print(f"DEBUG: GPU = {gpu_stats.name}. Max memory = {round(gpu_stats.total_memory/(1024**3),3)} GB.")
47
+
48
+ def check_ram(self):
49
+ from psutil import virtual_memory
50
+ ram_gb = virtual_memory().total / 1e9
51
+ print(f"DEBUG: Your runtime has {ram_gb:.1f} gigabytes of available RAM")
52
+ if ram_gb < 20:
53
+ print("DEBUG: Not using a high-RAM runtime")
54
+ else:
55
+ print("DEBUG: You are using a high-RAM runtime!")
56
+
57
+ def prepare_model(self):
58
+ print("DEBUG: Preparing vision model and tokenizer...")
59
+ self.model, original_tokenizer = FastVisionModel.from_pretrained(
60
+ model_name=self.config["model_name"],
61
+ load_in_4bit=self.config["load_in_4bit"],
62
+ use_gradient_checkpointing="unsloth"
63
+ )
64
+ print("DEBUG: Vision model and original tokenizer loaded.")
65
+ if original_tokenizer.pad_token is None:
66
+ original_tokenizer.pad_token = original_tokenizer.eos_token
67
+ original_tokenizer.model_max_length = self.config.get("max_seq_length", 2048)
68
+ self.hf_tokenizer = original_tokenizer
69
+
70
+ # Add vision-specific LoRA adapters
71
+ self.model = FastVisionModel.get_peft_model(
72
+ self.model,
73
+ finetune_vision_layers=self.config.get("finetune_vision_layers", False),
74
+ finetune_language_layers=self.config.get("finetune_language_layers", True),
75
+ finetune_attention_modules=self.config.get("finetune_attention_modules", True),
76
+ finetune_mlp_modules=self.config.get("finetune_mlp_modules", True),
77
+ r=16,
78
+ lora_alpha=16,
79
+ lora_dropout=0,
80
+ bias="none",
81
+ random_state=3407,
82
+ use_rslora=False,
83
+ loftq_config=None
84
+ )
85
+ print("DEBUG: Vision LoRA adapters added.")
86
+
87
+ def convert_sample(self, sample):
88
+ # Use a default instruction or one from config
89
+ instr = self.config.get("vision_instruction", "You are an expert radiographer. Describe accurately what you see in this image.")
90
+ conversation = [
91
+ {"role": "user", "content": [
92
+ {"type": "text", "text": instr},
93
+ {"type": "image", "image": sample["image"]}
94
+ ]},
95
+ {"role": "assistant", "content": [
96
+ {"type": "text", "text": sample["caption"]}
97
+ ]}
98
+ ]
99
+ return {"messages": conversation}
100
+
101
+ def load_datasets(self):
102
+ datasets = []
103
+ for dataset_info in self.config["dataset"]:
104
+ print("DEBUG: Loading vision dataset:", dataset_info)
105
+ ds = load_dataset(dataset_info["name"], split=dataset_info.get("split_type", "train"))
106
+ print("DEBUG: Converting dataset to vision conversation format...")
107
+ ds = ds.map(self.convert_sample)
108
+ datasets.append(ds)
109
+ combined = concatenate_datasets(datasets)
110
+ print("DEBUG: Combined vision dataset has", len(combined), "examples.")
111
+ return combined
112
+
113
+ def train_model(self):
114
+ print("DEBUG: Starting vision training...")
115
+ raw_dataset = self.load_datasets()
116
+
117
+ # Build training arguments using SFTConfig for vision tasks
118
+ sft_config = SFTConfig(
119
+ per_device_train_batch_size=self.config.get("per_device_train_batch_size", 2),
120
+ gradient_accumulation_steps=self.config.get("gradient_accumulation_steps", 4),
121
+ warmup_steps=self.config.get("warmup_steps", 5),
122
+ max_steps=self.config.get("max_steps", 30),
123
+ learning_rate=self.config.get("learning_rate", 2e-4),
124
+ fp16=self.config.get("fp16", not is_bf16_supported()),
125
+ bf16=self.config.get("bf16", is_bf16_supported()),
126
+ logging_steps=self.config.get("logging_steps", 1),
127
+ optim=self.config.get("optim", "adamw_8bit"),
128
+ weight_decay=self.config.get("weight_decay", 0.01),
129
+ lr_scheduler_type=self.config.get("lr_scheduler_type", "linear"),
130
+ seed=self.config.get("seed", 3407),
131
+ output_dir=self.config.get("output_dir", "outputs"),
132
+ report_to="none" if not os.getenv("PRAISON_WANDB") else "wandb",
133
+ remove_unused_columns=False,
134
+ dataset_text_field="",
135
+ dataset_kwargs={"skip_prepare_dataset": True},
136
+ dataset_num_proc=self.config.get("dataset_num_proc", 4),
137
+ max_seq_length=self.config.get("max_seq_length", 2048)
138
+ )
139
+
140
+ trainer = SFTTrainer(
141
+ model=self.model,
142
+ tokenizer=self.hf_tokenizer,
143
+ data_collator=UnslothVisionDataCollator(self.model, self.hf_tokenizer),
144
+ train_dataset=raw_dataset,
145
+ args=sft_config
146
+ )
147
+ print("DEBUG: Beginning vision trainer.train() ...")
148
+ trainer.train()
149
+ print("DEBUG: Vision training complete. Saving model and tokenizer locally...")
150
+ self.model.save_pretrained("lora_vision_model")
151
+ self.hf_tokenizer.save_pretrained("lora_vision_model")
152
+ print("DEBUG: Saved vision model and tokenizer to 'lora_vision_model'.")
153
+
154
+ def vision_inference(self, instruction, image):
155
+ FastVisionModel.for_inference(self.model)
156
+ messages = [
157
+ {"role": "user", "content": [
158
+ {"type": "image"},
159
+ {"type": "text", "text": instruction}
160
+ ]}
161
+ ]
162
+ input_text = self.hf_tokenizer.apply_chat_template(messages, add_generation_prompt=True)
163
+ inputs = self.hf_tokenizer(
164
+ image,
165
+ input_text,
166
+ add_special_tokens=False,
167
+ return_tensors="pt"
168
+ ).to("cuda")
169
+ outputs = self.model.generate(
170
+ **inputs,
171
+ max_new_tokens=128,
172
+ use_cache=True,
173
+ temperature=1.5,
174
+ min_p=0.1
175
+ )
176
+ print("DEBUG: Vision inference output:", self.hf_tokenizer.batch_decode(outputs))
177
+
178
+ def save_model_merged(self):
179
+ if os.path.exists(self.config["hf_model_name"]):
180
+ shutil.rmtree(self.config["hf_model_name"])
181
+ self.model.push_to_hub_merged(
182
+ self.config["hf_model_name"],
183
+ self.hf_tokenizer,
184
+ save_method="merged_16bit",
185
+ token=os.getenv("HF_TOKEN")
186
+ )
187
+
188
+ def push_model_gguf(self):
189
+ self.model.push_to_hub_gguf(
190
+ self.config["hf_model_name"],
191
+ self.hf_tokenizer,
192
+ quantization_method=self.config.get("quantization_method", "q4_k_m"),
193
+ token=os.getenv("HF_TOKEN")
194
+ )
195
+
196
+ def save_model_gguf(self):
197
+ self.model.save_pretrained_gguf(
198
+ self.config["hf_model_name"],
199
+ self.hf_tokenizer,
200
+ quantization_method="q4_k_m"
201
+ )
202
+
203
+ def run(self):
204
+ self.print_system_info()
205
+ self.check_gpu()
206
+ self.check_ram()
207
+ if self.config.get("train", "true").lower() == "true":
208
+ self.prepare_model()
209
+ self.train_model()
210
+
211
+
212
+ def main():
213
+ import argparse
214
+ parser = argparse.ArgumentParser(description="PraisonAI Vision Training Script")
215
+ parser.add_argument("command", choices=["train", "inference"], help="Command to execute")
216
+ parser.add_argument("--config", default="config.yaml", help="Path to configuration file")
217
+ args = parser.parse_args()
218
+
219
+ trainer_obj = TrainVisionModel(config_path=args.config)
220
+ if args.command == "train":
221
+ trainer_obj.run()
222
+ elif args.command == "inference":
223
+ # For inference, we load a sample image from the first dataset
224
+ instr = trainer_obj.config.get("vision_instruction", "You are an expert radiographer. Describe accurately what you see in this image.")
225
+ ds_info = trainer_obj.config["dataset"][0]
226
+ ds = load_dataset(ds_info["name"], split=ds_info.get("split_type", "train"))
227
+ sample_image = ds[0]["image"]
228
+ if trainer_obj.model is None or trainer_obj.hf_tokenizer is None:
229
+ trainer_obj.prepare_model()
230
+ trainer_obj.vision_inference(instr, sample_image)
231
+
232
+
233
+ if __name__ == "__main__":
234
+ main()
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "PraisonAI"
3
- version = "2.0.73"
3
+ version = "2.0.75"
4
4
  description = "PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human-agent collaboration."
5
5
  readme = "README.md"
6
6
  license = ""
@@ -84,7 +84,7 @@ autogen = ["pyautogen>=0.2.19", "praisonai-tools>=0.0.7", "crewai"]
84
84
 
85
85
  [tool.poetry]
86
86
  name = "PraisonAI"
87
- version = "2.0.73"
87
+ version = "2.0.75"
88
88
  description = "PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human–agent collaboration."
89
89
  authors = ["Mervin Praison"]
90
90
  license = ""
File without changes
File without changes
File without changes
File without changes