pilot.linkstec 0.0.90__py3-none-any.whl → 0.0.91__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
@@ -0,0 +1,75 @@
1
+ import requests
2
+
3
+ from pilot.config.config_reader import get_config
4
+ from pilot.logging.logger import get_logger
5
+
6
+
7
+ class AIClient:
8
+ def __init__(self):
9
+ self.logger = get_logger(__name__)
10
+ self.config_dto = get_config()
11
+ self.headers = {"Content-Type": "application/json;charset=utf-8"}
12
+
13
+ def call(self, user_prompt: str, system_prompt: str = "") -> str:
14
+ messages = []
15
+ if system_prompt:
16
+ messages.append({"role": "system", "content": system_prompt})
17
+ messages.append({"role": "user", "content": user_prompt})
18
+
19
+ request_data = self._build_request_payload(messages)
20
+
21
+ response_data = self._send_post_request(self.api_url, self.headers, request_data)
22
+ if not isinstance(response_data, dict):
23
+ self.logger.error("無効なAPI応答またはリクエスト失敗")
24
+ return ""
25
+
26
+ result_text = self._extract_response_content(response_data)
27
+ return result_text
28
+
29
+ def _build_request_payload(self, messages: list[dict]) -> dict:
30
+ raise NotImplementedError("サブクラスでリクエストペイロードの構築を実装してください")
31
+
32
+ def _send_post_request(self, url: str, headers: dict, data: dict) -> dict or str:
33
+ try:
34
+ response = requests.post(url, headers=headers, json=data)
35
+ except Exception as e:
36
+ self.logger.error(f"リクエスト失敗: {e}")
37
+ return ""
38
+ if response.status_code != 200:
39
+ self.logger.error(f"ステータスコード {response.status_code}: {response.text}")
40
+ return ""
41
+ try:
42
+ return response.json()
43
+ except Exception as e:
44
+ self.logger.error(f"JSON解析失敗: {e}")
45
+ return ""
46
+
47
+ def _extract_response_content(self, response: dict) -> str:
48
+ raise NotImplementedError("サブクラスでレスポンスの解析を実装してください")
49
+
50
+
51
+ class LMStudioClient(AIClient):
52
+ def __init__(self):
53
+ super().__init__()
54
+ self.api_url = self.config_dto.lm_studio_api_url
55
+ self.model_name = self.config_dto.lm_studio_model_name
56
+
57
+ def _build_request_payload(self, messages: list[dict]) -> dict:
58
+ payload = {
59
+ "model": self.model_name,
60
+ "stream": False,
61
+ "temperature": 0.8,
62
+ "max_tokens": 15000,
63
+ "messages": messages,
64
+ }
65
+ return payload
66
+
67
+ def _extract_response_content(self, response: dict) -> str:
68
+ if not isinstance(response, dict):
69
+ return str(response)
70
+ if "usage" in response:
71
+ self.logger.debug(f"使用状況: {response['usage']}")
72
+ choices = response.get("choices", [])
73
+ if choices:
74
+ return choices[0].get("message", {}).get("content") or str(response)
75
+ return str(response)
@@ -1,39 +1,54 @@
1
1
  import configparser
2
- import os
3
2
  import inspect
3
+ import os
4
4
  from dataclasses import dataclass
5
- from typing import List
5
+ from typing import Optional
6
+
6
7
 
7
8
  @dataclass
8
9
  class ConfigDTO:
9
- work_space: str
10
- threads: int
11
10
  project: str
11
+ log_level: str
12
+ threads: int
13
+ lm_studio_api_url: str
14
+ lm_studio_model_name: str
15
+ work_space: str
16
+ copy_path: str
17
+ json_file_path:str
12
18
  steps: list[str]
13
- skipsteps: list[str]
14
- runsteps: list[str]
15
- multisteps: list[str]
19
+
16
20
 
17
21
  class ConfigReader:
18
- def __init__(self, filename = None):
19
- filepath = None
20
- if filename is None:
21
- filepath = self.find_config_path()
22
-
23
- if filename is not None:
24
- cwd = os.getcwd()
25
- filepath = os.path.join(cwd, 'config', filename)
26
- if not os.path.exists(filepath):
27
- raise FileNotFoundError(f"Configuration file not found: {filepath}")
28
-
29
- self.config = configparser.ConfigParser()
30
- self.config.optionxform = str
31
-
32
- with open(filepath, 'r', encoding='utf-8') as f:
33
- content = f.read()
34
- if not content.lstrip().startswith('['):
35
- content = '[DEFAULT]\n' + content
36
- self.config.read_string(content)
22
+ _instance = None
23
+ _loaded = False
24
+
25
+ def __new__(cls, filepath=None):
26
+ if cls._instance is None:
27
+ cls._instance = super().__new__(cls)
28
+ return cls._instance
29
+
30
+ def __init__(self, filepath=None):
31
+ if self._loaded:
32
+ return
33
+
34
+ try:
35
+ if filepath is None:
36
+ filepath = self.find_config_path()
37
+ if not os.path.exists(filepath):
38
+ raise FileNotFoundError(f"設定ファイルが見つかりません: {filepath}")
39
+
40
+ self.config = configparser.ConfigParser()
41
+ self.config.optionxform = str
42
+ with open(filepath, 'r', encoding='utf-8') as f:
43
+ content = f.read()
44
+ if not content.lstrip().startswith('['):
45
+ content = '[DEFAULT]\n' + content
46
+ self.config.read_string(content)
47
+
48
+ self._loaded = True
49
+ except Exception as e:
50
+ print(f"設定ファイル読み込みエラー: {e}")
51
+ raise
37
52
 
38
53
  @classmethod
39
54
  def find_config_path(cls):
@@ -52,10 +67,11 @@ class ConfigReader:
52
67
 
53
68
  base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
54
69
  fallback_path = os.path.join(base_dir, 'config', 'control.properties')
70
+
55
71
  if os.path.exists(fallback_path):
56
72
  return fallback_path
57
73
 
58
- raise FileNotFoundError("control.properties not found in expected locations")
74
+ raise FileNotFoundError("control.properties が期待される場所に見つかりません")
59
75
 
60
76
  def get(self, section, option, fallback=None, cast_type=str):
61
77
  try:
@@ -71,25 +87,47 @@ class ConfigReader:
71
87
  return fallback
72
88
 
73
89
  def get_dto(self) -> ConfigDTO:
74
- input_path = self.get('DEFAULT', 'input_path', fallback='.')
75
- work_space = self.get('DEFAULT', 'work_space', fallback='.')
76
- threads = int(self.get('DEFAULT', 'threads', fallback=1))
77
90
  project = self.get('DEFAULT', 'project', fallback='')
91
+ log_level = self.get('DEFAULT', 'log_level', fallback='INFO')
92
+ threads = self.get('DEFAULT', 'threads', fallback=1, cast_type=int)
93
+ lm_studio_api_url = self.get('DEFAULT', 'lm_studio_api_url', fallback='.')
94
+ lm_studio_model_name = self.get('DEFAULT', 'lm_studio_model_name', fallback='.')
95
+ work_space = self.get('DEFAULT', 'work_space', fallback='.')
96
+ copy_path = self.get('DEFAULT', 'copy_file_path', fallback='.')
97
+ json_file_path = self.get('DEFAULT', 'json_file_path', fallback='.')
78
98
  steps_str = self.get('DEFAULT', 'steps', fallback='')
99
+
79
100
  steps = [s.strip() for s in steps_str.split(',')] if steps_str else []
80
- skipsteps_str = self.get('DEFAULT', 'skipsteps', fallback='')
81
- skipsteps = [s.strip() for s in skipsteps_str.split(',')] if skipsteps_str else []
82
- runsteps_str = self.get('DEFAULT', 'runsteps', fallback='')
83
- runsteps = [s.strip() for s in runsteps_str.split(',')] if runsteps_str else []
84
- multisteps_str = self.get('DEFAULT', 'multisteps', fallback='')
85
- multisteps = [s.strip() for s in multisteps_str.split(',')] if multisteps_str else []
86
101
 
87
102
  return ConfigDTO(
88
- work_space=work_space,
89
- threads=threads,
90
103
  project=project,
91
- steps=steps,
92
- skipsteps=skipsteps,
93
- runsteps=runsteps,
94
- multisteps=multisteps
95
- )
104
+ log_level=log_level,
105
+ threads=threads,
106
+ lm_studio_api_url=lm_studio_api_url,
107
+ lm_studio_model_name=lm_studio_model_name,
108
+ work_space=work_space,
109
+ copy_path=copy_path,
110
+ json_file_path=json_file_path,
111
+ steps=steps
112
+ )
113
+
114
+
115
+ # 全局設定管理用の変数
116
+ _global_config: Optional[ConfigDTO] = None
117
+
118
+
119
+ def init_config(filepath=None):
120
+ global _global_config
121
+ try:
122
+ config_reader = ConfigReader(filepath)
123
+ _global_config = config_reader.get_dto()
124
+ except Exception as e:
125
+ print(f"設定初期化エラー: {e}")
126
+ raise
127
+
128
+
129
+ def get_config() -> ConfigDTO:
130
+ global _global_config
131
+ if _global_config is None:
132
+ raise RuntimeError("設定が初期化されていません。init_config() を最初に呼び出してください。")
133
+ return _global_config
File without changes
File without changes
@@ -0,0 +1,16 @@
1
+ import threading
2
+
3
+ from pilot.job.impl.base_job import BaseJob
4
+
5
+ from pilot.conver.converfileEncodding import nkf_convert
6
+
7
+
8
+ class EncodingTransformerJob(BaseJob):
9
+ _begin_file_lock = threading.Lock()
10
+ def run(self):
11
+ with self._begin_file_lock:
12
+ if not self.change_current_trg_to_begin():
13
+ return
14
+ nkf_args = ['-w', '--overwrite']
15
+ nkf_convert(self.file_path, nkf_args)
16
+ super().run()
@@ -0,0 +1,27 @@
1
+ import threading
2
+ from pathlib import Path
3
+
4
+ from pilot.job.impl.base_job import BaseJob
5
+
6
+ class TabReplaceJob(BaseJob):
7
+ _begin_file_lock = threading.Lock()
8
+ def run(self):
9
+ with self._begin_file_lock:
10
+ if not self.change_current_trg_to_begin():
11
+ return
12
+ self.replace_tabs_with_spaces()
13
+ super().run()
14
+
15
+ def replace_tabs_with_spaces(self, tab_width: int = 4):
16
+ replaced_text =[]
17
+ src_path = Path(self.file_path)
18
+ spaces = ' ' * tab_width
19
+ with open(self.file_path, 'r', encoding='utf-8', newline='') as rf:
20
+ for line in rf:
21
+ replaced_text.append(line.replace('\t', spaces))
22
+
23
+ tmp_path = src_path.parent / (src_path.name + '.tmp')
24
+ with open(tmp_path, 'w', encoding='utf-8', newline='') as wf:
25
+ wf.writelines(replaced_text)
26
+
27
+ tmp_path.replace(src_path)
File without changes
@@ -0,0 +1,42 @@
1
+ import json
2
+ import os
3
+ import threading
4
+ import time
5
+
6
+ from pilot.job.impl.base_job import BaseJob
7
+
8
+ from pilot.generater.vertexai import VertexAISingleton
9
+
10
+ class generateJsonBaseJob(BaseJob):
11
+
12
+ prompt_content: str
13
+ result_content: str
14
+ result_file_path: str
15
+
16
+ def run(self):
17
+ #with self._begin_file_lock:
18
+ # if not self.change_current_trg_to_begin():
19
+ # return
20
+ #prompt = self.get_file_content()
21
+ prompt = self.prompt_content
22
+ # トークン数チェック
23
+ vertexai = VertexAISingleton.get_instance()
24
+ token_count = vertexai.count_tokens(prompt)
25
+ if token_count == 0:
26
+ super().run()
27
+ return
28
+ if token_count > 900000:
29
+ print(f"警告: promptのトークン数が900000を超えています ({token_count} tokens)")
30
+ super().run()
31
+ return
32
+ # VertexAI で生成
33
+ start = time.time()
34
+ result = vertexai.generate_content(prompt)
35
+ end = time.time()
36
+ print(f"Ai 処理時間 {self.file_path}: {end - start:.2f}秒")
37
+
38
+ result_content = result.get('response', '')
39
+ data = json.loads(result_content)
40
+ with open(self.result_file_path, 'w', encoding='utf-8') as f:
41
+ json.dump(data, f, ensure_ascii=False, indent=2)
42
+ super().run()
@@ -0,0 +1,40 @@
1
+ import json
2
+ import os
3
+ import threading
4
+ import time
5
+
6
+ from pilot.job.impl.base_job import BaseJob
7
+
8
+ from pilot.generater.vertexai import VertexAISingleton
9
+
10
+ class textBaseJob(BaseJob):
11
+
12
+ prompt_content: str
13
+ result_content: str
14
+ result_file_path: str
15
+
16
+ def run(self):
17
+ #with self._begin_file_lock:
18
+ # if not self.change_current_trg_to_begin():
19
+ # return
20
+ #prompt = self.get_file_content()
21
+ prompt = self.prompt_content
22
+ # トークン数チェック
23
+ vertexai = VertexAISingleton.get_instance()
24
+ token_count = vertexai.count_tokens(prompt)
25
+ if token_count == 0:
26
+ super().run()
27
+ return
28
+ if token_count > 900000:
29
+ print(f"警告: promptのトークン数が900000を超えています ({token_count} tokens)")
30
+ super().run()
31
+ return
32
+ # VertexAI で生成
33
+ start = time.time()
34
+ result = vertexai.generate_content(prompt)
35
+ end = time.time()
36
+ print(f"AI 処理時間 {self.file_path}: {end - start:.2f}秒")
37
+ result_content = result.get('response', '')
38
+ with open(self.result_file_path, 'w', encoding='utf-8') as f:
39
+ f.write(result_content)
40
+ super().run()
@@ -67,7 +67,11 @@ class BaseJob(JobInterface):
67
67
  self._trg_file_path = value
68
68
 
69
69
 
70
+ def prerun(self):
71
+ pass
70
72
 
73
+ def postrun(self):
74
+ self.change_current_trg_to_end()
71
75
 
72
76
  def run(self):
73
77
  pass
@@ -31,6 +31,7 @@ class BaseUnit(UnitInterface):
31
31
  job.file_path = file_path
32
32
  if self.job_need_run(job, filename, index):
33
33
  job.run()
34
+ job.postrun()
34
35
 
35
36
  def job_need_run(self, job:BaseJob,filename: str,index):
36
37
  return True
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pilot.linkstec
3
- Version: 0.0.90
3
+ Version: 0.0.91
4
4
  Summary: pilot of the ship, a tool for managing and deploying Python projects.
5
5
  Author-email: wanglr <wanglr1980@gmail.com>
6
6
  License-Expression: MIT
@@ -9,8 +9,10 @@ pilot/base/file_operation.py,sha256=SEguSMtkwKnOLX1KgMmFSLlPjm2IOhgUuRy07fKFCxk,
9
9
  pilot/base/get_file_encoding.py,sha256=U118_SxBXz69hhY8FGZWNQDxB1zfMG5_7gkAb6O3uG0,400
10
10
  pilot/base/make_parsing_java_file_order_base.py,sha256=mK4tIN2EIHPm7CkPrYkfVI2xA8nW1kKPsGWC4A9zat4,6310
11
11
  pilot/base/split_file_base.py,sha256=CuPI9XHlSTTkLRNXW6SNEKkdSZBOMuy685e2TcnWPkY,12625
12
+ pilot/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ pilot/client/ai_client.py,sha256=0n_YbjEb_QbgDAnUt_d1fJ4xYVzZmMxfJBNE5Yff9io,2919
12
14
  pilot/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- pilot/config/config_reader.py,sha256=MchG-9j-Xfy8AquL_6tlvqQR65MFJ3c3hwWBl6IF2jw,3750
15
+ pilot/config/config_reader.py,sha256=DxTkCft9s9iuVoApWJ276ATIgM5vSiYjha4nhRVUuM0,4703
14
16
  pilot/control/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
17
  pilot/control/control_interface.py,sha256=zGv380oQgAKPAIHDHeFdPYzhj2Ngo2T66NWlNloA7vY,124
16
18
  pilot/control/impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -43,8 +45,15 @@ pilot/generater/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
45
  pilot/generater/vertexai.py,sha256=SOFfl0qCuLhfjeIoSU7Tk-I7ZB6ZrOyGme2rXDYCGzk,2599
44
46
  pilot/job/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
47
  pilot/job/job_interface.py,sha256=EKtuj0IcdolP494aAgTtctgamyQIoFXVwRORwOQck7A,124
48
+ pilot/job/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
+ pilot/job/base/convert/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
+ pilot/job/base/convert/encodingTransformerJob.py,sha256=tJI2JcBK3869pIgJxf9WFa7D-wCnHHO1aU8vQo7qjds,457
51
+ pilot/job/base/convert/tabReplaceJob.py,sha256=ev5uoPbiwhVCSDPdonvFDnWI-vi4R-4Adoa4eJddL9w,917
52
+ pilot/job/base/generate/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
+ pilot/job/base/generate/generateJsonBaseJob.py,sha256=5klyS0tj9YTAcLVldcxUe1GXnWYXsQhvpcB7bRjq_n4,1377
54
+ pilot/job/base/generate/generateTextBaseJob.py,sha256=yJVzeM_87T_lqo3x39j9Mi4IuKwGj_Ww3bxXUuY_F6o,1299
46
55
  pilot/job/impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
- pilot/job/impl/base_job.py,sha256=7jxh4wREvlhFruCHA0VTnBrcg1f1sleMYo5gcvK8hdg,14642
56
+ pilot/job/impl/base_job.py,sha256=PpV4g7NiWPICojp9cSv4iDWnONHWQYYjYdYfzengxBg,14745
48
57
  pilot/logging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
58
  pilot/logging/logger.py,sha256=TF7eGr3w8GK5v4sf71lDt97uVoBtCgqrZuCdbMmeQBU,1815
50
59
  pilot/processor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -56,11 +65,11 @@ pilot/splitters/cobolsplitter.py,sha256=oPwxKRjA7TyXWaWV3jdy59lJZy1mRn6yxD9ivqFY
56
65
  pilot/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
66
  pilot/unit/unit_interface.py,sha256=fE8N4h_rZU-dWLHy9o0EE3yyErGmRyIuGUDb-zqe7qo,167
58
67
  pilot/unit/impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
- pilot/unit/impl/base_unit.py,sha256=LsFPpL28aSNv5rsZhfKv6CWhAw1XR4n-A6FOn2RBrZo,1272
68
+ pilot/unit/impl/base_unit.py,sha256=GO5tXlyDLgYXhgQL1u910Kd9LyvHFq0Kj1zATOL4Gw0,1307
60
69
  pilot/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
70
  pilot/util/files.py,sha256=v9uzfzo3Aq4xgnUIASEZeBJoA2nD9Qz_EA3P-FwzGFQ,1896
62
- pilot_linkstec-0.0.90.dist-info/licenses/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
63
- pilot_linkstec-0.0.90.dist-info/METADATA,sha256=iSPnwKqO0yHZW8_WqwTvUl_Ta6HUmJkXZcbJjOxMSS4,679
64
- pilot_linkstec-0.0.90.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
65
- pilot_linkstec-0.0.90.dist-info/top_level.txt,sha256=BijnVJdXnIPxxx3s60M848seL4Z12gNUPod6KPJxK9c,6
66
- pilot_linkstec-0.0.90.dist-info/RECORD,,
71
+ pilot_linkstec-0.0.91.dist-info/licenses/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
72
+ pilot_linkstec-0.0.91.dist-info/METADATA,sha256=m_dqJdh5Rw5Q1urOdL-y8u8uDxigGKmEaO51dtEV-jY,679
73
+ pilot_linkstec-0.0.91.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
74
+ pilot_linkstec-0.0.91.dist-info/top_level.txt,sha256=BijnVJdXnIPxxx3s60M848seL4Z12gNUPod6KPJxK9c,6
75
+ pilot_linkstec-0.0.91.dist-info/RECORD,,