codefinetuner 0.1.0__py3-none-any.whl

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.
File without changes
File without changes
@@ -0,0 +1,107 @@
1
+ import logging
2
+ import importlib.metadata
3
+ import httpx
4
+ from dataclasses import dataclass, field, fields
5
+ from pathlib import Path
6
+ from omegaconf import OmegaConf
7
+
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ @dataclass
13
+ class Config:
14
+ workspace_path: Path | None = None
15
+ convert_hf_to_gguf_local_path: Path = field(init=False)
16
+ lora_model_path: Path = field(init=False)
17
+ lora_model_gguf_path: Path = field(init=False)
18
+
19
+ @classmethod
20
+ def load_from_yaml(cls, yaml_path: Path) -> "Config":
21
+ if not yaml_path.exists():
22
+ raise FileNotFoundError(f"Configuration file not found at: {yaml_path}")
23
+
24
+ logger.info(f"Loading configuration from {yaml_path}")
25
+ config_dict = OmegaConf.structured(cls)
26
+ try:
27
+ yaml_file_node = OmegaConf.load(yaml_path)
28
+ except Exception as e:
29
+ raise ValueError(f"Failed to load YAML config {yaml_path}") from e
30
+
31
+ yaml_file_dict = OmegaConf.to_container(yaml_file_node, resolve=True)
32
+ yaml_convert_dict = yaml_file_dict.get("convert", {})
33
+
34
+ yaml_convert_valid_dict = {}
35
+ # Filter YAML fields to include only those defined in the Config dataclass.
36
+ # This prevents OmegaConf from raising an AttributeError when encountering
37
+ # global YAML anchors or keys not present in the current Config dataclass.
38
+ for field in fields(cls):
39
+ if field.name in yaml_convert_dict:
40
+ yaml_convert_valid_dict[field.name] = yaml_convert_dict[field.name]
41
+ logger.debug(f"Filtered YAML configuration: {yaml_convert_valid_dict}")
42
+
43
+ merged_config_dict = OmegaConf.merge(config_dict, yaml_convert_valid_dict)
44
+ return OmegaConf.to_object(merged_config_dict)
45
+
46
+ def __post_init__(self) -> None:
47
+ self._setup_paths()
48
+ self._ensure_output_paths_exist()
49
+ self._sync_converter_script_version()
50
+
51
+ def _setup_paths(self) -> None:
52
+ if self.workspace_path is None:
53
+ self.workspace_path = Path.cwd()
54
+
55
+ pkg_root = self.workspace_path / "src" / "codefinetuner" / "convert"
56
+ self.convert_hf_to_gguf_local_path = pkg_root / "convert_hf_to_gguf.py"
57
+ self.lora_model_path = self.workspace_path / "outputs" / "finetune" / "results" / "lora_model"
58
+ self.lora_model_gguf_path = self.workspace_path / "outputs" / "convert" / "results" / "lora_model.gguf"
59
+
60
+ def _ensure_output_paths_exist(self) -> None:
61
+ parent_dir = self.lora_model_gguf_path.parent
62
+ if not parent_dir.exists():
63
+ parent_dir.mkdir(parents=True, exist_ok=True)
64
+ logger.debug(f"Created directory: {parent_dir}")
65
+
66
+ def _sync_converter_script_version(self) -> None:
67
+ """
68
+ Downloads the convert_hf_to_gguf.py script from llama.cpp github repo
69
+ if it is missing or version mismatched with localy installed gguf package (in .venv).
70
+ """
71
+ try:
72
+ current_gguf_version = importlib.metadata.version("gguf")
73
+ version_tag = f"gguf-v{current_gguf_version}"
74
+ except importlib.metadata.PackageNotFoundError:
75
+ logger.warning("gguf package not found. Defaulting to master branch.")
76
+ version_tag = "master"
77
+ current_gguf_version = "master"
78
+
79
+ version_marker_path = self.convert_hf_to_gguf_local_path.with_suffix(".version")
80
+
81
+ # check if we can skip the download
82
+ if self.convert_hf_to_gguf_local_path.exists() and version_marker_path.exists():
83
+ last_version = version_marker_path.read_text().strip()
84
+ if last_version == current_gguf_version:
85
+ logger.debug(f"convert_hf_to_gguf.py script is up to date (version {current_gguf_version}).")
86
+ return
87
+
88
+ # proceed with download
89
+ github_url = f"https://raw.githubusercontent.com/ggerganov/llama.cpp/{version_tag}/convert_hf_to_gguf.py"
90
+ logger.info(f"Syncing convert_hf_to_gguf.py script for version {version_tag}...")
91
+
92
+ try:
93
+ with httpx.Client(follow_redirects=True) as client:
94
+ response = client.get(github_url)
95
+ if response.status_code == 404 and version_tag != "master":
96
+ logger.warning(f"Version {version_tag} not found. Falling back to master.")
97
+ response = client.get("https://raw.githubusercontent.com/ggerganov/llama.cpp/master/convert_hf_to_gguf.py")
98
+
99
+ response.raise_for_status()
100
+ self.convert_hf_to_gguf_local_path.write_text(response.text, encoding="utf-8")
101
+ version_marker_path.write_text(current_gguf_version) # save the version marker to prevent re-downloading next time
102
+
103
+ except Exception as e:
104
+ if self.convert_hf_to_gguf_local_path.exists():
105
+ logger.error(f"Failed to update convert_hf_to_gguf.py scprit but local copy exists. Proceeding. Error: {e}")
106
+ else:
107
+ raise RuntimeError(f"Failed to download convert_hf_to_gguf.py script and no local copy found") from e