pro-craft 0.1.10__py3-none-any.whl → 0.1.12__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.

Potentially problematic release.


This version of pro-craft might be problematic. Click here for more details.

@@ -489,20 +489,25 @@ class Intel():
489
489
 
490
490
  def intellect_remove_format(self,
491
491
  input_data: dict | str,
492
- OutputFormat: object,
493
492
  prompt_id: str,
493
+ OutputFormat: object = None,
494
+ ExtraFormats: list[object] = [],
494
495
  version: str = None,
495
496
  inference_save_case = True,
496
497
  ):
497
-
498
- base_format_prompt = """
498
+
499
+ if OutputFormat:
500
+ base_format_prompt = """
499
501
  按照一定格式输出, 以便可以通过如下校验
500
502
 
501
503
  使用以下正则检出
502
504
  "```json([\s\S]*?)```"
503
505
  使用以下方式验证
504
506
  """
505
- output_format = base_format_prompt + inspect.getsource(OutputFormat)
507
+ output_format = base_format_prompt + "\n".join([inspect.getsource(outputformat) for outputformat in ExtraFormats]) + inspect.getsource(OutputFormat)
508
+
509
+ else:
510
+ output_format = ""
506
511
 
507
512
  ai_result = self.intellect_remove(
508
513
  input_data=input_data,
@@ -512,21 +517,26 @@ class Intel():
512
517
  inference_save_case=inference_save_case
513
518
  )
514
519
 
515
- try:
516
- ai_result = json.loads(extract_(ai_result,r'json'))
517
- OutputFormat(**ai_result)
518
- except ValidationError as e:
519
- log_ = "记忆卡片合并 - 大模型生成的格式未通过校验"
520
- logger.error(log_)
521
- logger.error(f"错误类型: {type(e)}")
522
- logger.error(f"错误信息: {e}")
523
- logger.error(f"错误详情 (errors()): {e.errors()}")
524
- logger.error(f"错误详情 (json()): {e.json(indent=2)}")
525
- raise ValidationError(log_)
526
-
520
+ if OutputFormat:
521
+ try:
522
+ ai_result = json.loads(extract_(ai_result,r'json'))
523
+ OutputFormat(**ai_result)
524
+ except ValidationError as e:
525
+ log_ = "记忆卡片合并 - 大模型生成的格式未通过校验"
526
+ logger.error(log_)
527
+ logger.error(f"错误类型: {type(e)}")
528
+ logger.error(f"错误信息: {e}")
529
+ logger.error(f"错误详情 (errors()): {e.errors()}")
530
+ logger.error(f"错误详情 (json()): {e.json(indent=2)}")
531
+ raise ValidationError(log_)
532
+ else:
533
+ try:
534
+ assert isinstance(ai_result,str)
535
+ except AssertionError as e:
536
+ logger.error("错误了问题")
537
+
527
538
  return ai_result
528
539
 
529
-
530
540
  def intellect_remove_warp(self,prompt_id: str):
531
541
  def outer_packing(func):
532
542
  @functools.wraps(func)
@@ -68,9 +68,8 @@ class AsyncIntel():
68
68
  ):
69
69
  database_url = database_url or os.getenv("database_url")
70
70
  assert database_url
71
-
72
- # async_engine
73
- self.async_engine = create_async_engine(database_url, echo=True,
71
+
72
+ self.engine = create_async_engine(database_url, echo=True,
74
73
  pool_size=10, # 连接池中保持的连接数
75
74
  max_overflow=20, # 当pool_size不够时,允许临时创建的额外连接数
76
75
  pool_recycle=3600, # 每小时回收一次连接
@@ -87,10 +86,10 @@ class AsyncIntel():
87
86
  self.llm = BianXieAdapter()
88
87
 
89
88
  async def create_database(self):
90
- async with self.async_engine.begin() as conn:
89
+ async with self.engine.begin() as conn:
91
90
  await conn.run_sync(PromptBase.metadata.create_all)
92
91
 
93
- async def _aget_latest_prompt_version(self,target_prompt_id,session):
92
+ async def _get_latest_prompt_version(self,target_prompt_id,session):
94
93
  """
95
94
  获取指定 prompt_id 的最新版本数据,通过创建时间判断。
96
95
  """
@@ -113,7 +112,7 @@ class AsyncIntel():
113
112
  editing_log(f"未找到 prompt_id '{target_prompt_id}' 的任何版本。")
114
113
  return result
115
114
 
116
- async def _aget_specific_prompt_version(self,target_prompt_id, target_version,session):
115
+ async def _get_specific_prompt_version(self,target_prompt_id, target_version,session):
117
116
  """
118
117
  获取指定 prompt_id 和特定版本的数据。
119
118
 
@@ -141,7 +140,7 @@ class AsyncIntel():
141
140
  editing_log(f"未找到 prompt_id '{target_prompt_id}', 版本 '{target_version}' 的提示词数据。")
142
141
  return specific_prompt
143
142
 
144
- async def aget_prompts_from_sql(self,
143
+ async def get_prompts_from_sql(self,
145
144
  prompt_id: str,
146
145
  version = None,
147
146
  session = None) -> Prompt:
@@ -150,15 +149,15 @@ class AsyncIntel():
150
149
  """
151
150
  # 查看是否已经存在
152
151
  if version:
153
- prompts_obj = await self._aget_specific_prompt_version(prompt_id,version,session=session)
152
+ prompts_obj = await self._get_specific_prompt_version(prompt_id,version,session=session)
154
153
  if not prompts_obj:
155
- prompts_obj = await self._aget_latest_prompt_version(prompt_id,session = session)
154
+ prompts_obj = await self._get_latest_prompt_version(prompt_id,session = session)
156
155
  else:
157
- prompts_obj = await self._aget_latest_prompt_version(prompt_id,session = session)
156
+ prompts_obj = await self._get_latest_prompt_version(prompt_id,session = session)
158
157
  return prompts_obj
159
158
 
160
159
 
161
- async def asave_prompt_increment_version(self,
160
+ async def save_prompt_increment_version(self,
162
161
  prompt_id: str,
163
162
  new_prompt: str,
164
163
  use_case:str = "",
@@ -171,7 +170,7 @@ class AsyncIntel():
171
170
  input_data 指的是输入用例, 可以为空
172
171
  """
173
172
  # 查看是否已经存在
174
- prompts_obj = await self.aget_prompts_from_sql(prompt_id=prompt_id,session=session)
173
+ prompts_obj = await self.get_prompts_from_sql(prompt_id=prompt_id,session=session)
175
174
 
176
175
  if prompts_obj:
177
176
  # 如果存在版本加1
@@ -198,7 +197,7 @@ class AsyncIntel():
198
197
  session.add(prompt1)
199
198
  await session.commit() # 提交事务,将数据写入数据库
200
199
 
201
- async def asave_use_case_by_sql(self,
200
+ async def save_use_case_by_sql(self,
202
201
  prompt_id: str,
203
202
  use_case:str = "",
204
203
  output = "",
@@ -237,7 +236,7 @@ class AsyncIntel():
237
236
 
238
237
  s_prompt = extract_(system_result,pattern_key=r"prompt")
239
238
  chat_history = s_prompt or system_result
240
- await self.asave_prompt_increment_version(prompt_id,
239
+ await self.save_prompt_increment_version(prompt_id,
241
240
  new_prompt = chat_history,
242
241
  input_data = " summary ",
243
242
  session = session)
@@ -279,20 +278,20 @@ class AsyncIntel():
279
278
  {opinion}
280
279
  """
281
280
 
282
- prompt, _ = await self.aget_prompts_from_sql(prompt_id = prompt_id,version = version)
281
+ prompt, _ = await self.get_prompts_from_sql(prompt_id = prompt_id,version = version)
283
282
  if demand:
284
283
  new_prompt = await self.llm.aproduct(
285
284
  change_by_opinion_prompt.format(old_system_prompt=prompt, opinion=demand)
286
285
  )
287
286
  else:
288
287
  new_prompt = prompt
289
- await self.asave_prompt_increment_version(prompt_id = prompt_id,
288
+ await self.save_prompt_increment_version(prompt_id = prompt_id,
290
289
  new_prompt = new_prompt,
291
290
  input_data = " finetune ",
292
291
  session = session)
293
292
 
294
293
 
295
- async def apush_action_order(self,demand : str,prompt_id: str,
294
+ async def push_action_order(self,demand : str,prompt_id: str,
296
295
  action_type = 'train'):
297
296
 
298
297
  """
@@ -302,11 +301,11 @@ class AsyncIntel():
302
301
  将打算修改的状态推上数据库 # 1
303
302
  """
304
303
  # 查看是否已经存在
305
- async with create_async_session(self.async_engine) as session:
304
+ async with create_async_session(self.engine) as session:
306
305
 
307
- latest_prompt = await self.aget_prompts_from_sql(prompt_id=prompt_id,session=session)
306
+ latest_prompt = await self.get_prompts_from_sql(prompt_id=prompt_id,session=session)
308
307
 
309
- await self.asave_prompt_increment_version(prompt_id=latest_prompt.prompt_id,
308
+ await self.save_prompt_increment_version(prompt_id=latest_prompt.prompt_id,
310
309
  new_prompt = latest_prompt.prompt,
311
310
  use_case = latest_prompt.use_case,
312
311
  action_type=action_type,
@@ -319,7 +318,7 @@ class AsyncIntel():
319
318
 
320
319
 
321
320
 
322
- async def aintellect_remove(self,
321
+ async def intellect_remove(self,
323
322
  input_data: dict | str,
324
323
  output_format: str,
325
324
  prompt_id: str,
@@ -333,18 +332,18 @@ class AsyncIntel():
333
332
  input_ = input_data
334
333
 
335
334
  # 查数据库, 获取最新提示词对象
336
- async with create_async_session(self.async_engine) as session:
337
- result_obj = await self.aget_prompts_from_sql(prompt_id=prompt_id,session=session)
335
+ async with create_async_session(self.engine) as session:
336
+ result_obj = await self.get_prompts_from_sql(prompt_id=prompt_id,session=session)
338
337
 
339
338
 
340
339
  if result_obj is None:
341
- await self.asave_prompt_increment_version(
340
+ await self.save_prompt_increment_version(
342
341
  prompt_id = prompt_id,
343
342
  new_prompt = "做一些处理",
344
343
  use_case = input_,
345
344
  session = session
346
345
  )
347
- ai_result = await self.aintellect_remove(input_data = input_data,
346
+ ai_result = await self.intellect_remove(input_data = input_data,
348
347
  output_format = output_format,
349
348
  prompt_id = prompt_id,
350
349
  version = version,
@@ -357,7 +356,7 @@ class AsyncIntel():
357
356
  # 直接推理即可
358
357
  ai_result = await self.llm.aproduct(prompt + output_format + "\n-----input----\n" + input_)
359
358
  if inference_save_case:
360
- await self.asave_use_case_by_sql(prompt_id,
359
+ await self.save_use_case_by_sql(prompt_id,
361
360
  use_case = input_,
362
361
  output = ai_result,
363
362
  solution = "备注/理想回复",
@@ -386,7 +385,7 @@ class AsyncIntel():
386
385
 
387
386
  ai_result = await self.llm.aproduct(input_prompt)
388
387
  chat_history = input_prompt + "\nassistant:\n" + ai_result # 用聊天记录作为完整提示词
389
- await self.asave_prompt_increment_version(prompt_id, chat_history,
388
+ await self.save_prompt_increment_version(prompt_id, chat_history,
390
389
  use_case = input_,
391
390
  session = session)
392
391
 
@@ -426,7 +425,7 @@ class AsyncIntel():
426
425
 
427
426
  return ai_result
428
427
 
429
- async def aintellect_stream_remove(self,
428
+ async def intellect_stream_remove(self,
430
429
  input_data: dict | str,
431
430
  output_format: str,
432
431
  prompt_id: str,
@@ -441,18 +440,18 @@ class AsyncIntel():
441
440
 
442
441
 
443
442
  # 查数据库, 获取最新提示词对象
444
- with create_session(self.async_engine) as session:
445
- result_obj = await self.aget_prompts_from_sql(prompt_id=prompt_id,session=session)
443
+ with create_session(self.engine) as session:
444
+ result_obj = await self.get_prompts_from_sql(prompt_id=prompt_id,session=session)
446
445
 
447
446
  '''
448
447
  if result_obj is None:
449
- await self.asave_prompt_increment_version(
448
+ await self.save_prompt_increment_version(
450
449
  prompt_id = prompt_id,
451
450
  new_prompt = "做一些处理",
452
451
  use_case = input_,
453
452
  session = session
454
453
  )
455
- ai_result = await self.aintellect_stream_remove(input_data = input_data,
454
+ ai_result = await self.intellect_stream_remove(input_data = input_data,
456
455
  output_format = output_format,
457
456
  prompt_id = prompt_id,
458
457
  version = version,
@@ -470,7 +469,7 @@ class AsyncIntel():
470
469
  ai_result += word
471
470
  yield word
472
471
  if inference_save_case:
473
- await self.asave_use_case_by_sql(prompt_id,
472
+ await self.save_use_case_by_sql(prompt_id,
474
473
  use_case = input_,
475
474
  output = ai_result,
476
475
  solution = "备注/理想回复",
@@ -504,7 +503,7 @@ class AsyncIntel():
504
503
  yield word
505
504
 
506
505
  chat_history = input_prompt + "\nassistant:\n" + ai_result # 用聊天记录作为完整提示词
507
- await self.asave_prompt_increment_version(prompt_id, chat_history,
506
+ await self.save_prompt_increment_version(prompt_id, chat_history,
508
507
  use_case = input_,
509
508
  session = session)
510
509
 
@@ -555,7 +554,7 @@ class AsyncIntel():
555
554
  else:
556
555
  raise
557
556
 
558
- async def aintellect_remove_format(self,
557
+ async def intellect_remove_format(self,
559
558
  input_data: dict | str,
560
559
  OutputFormat: object,
561
560
  prompt_id: str,
@@ -573,7 +572,7 @@ class AsyncIntel():
573
572
  """
574
573
  output_format = base_format_prompt + "\n".join([inspect.getsource(outputformat) for outputformat in ExtraFormats]) + inspect.getsource(OutputFormat)
575
574
 
576
- ai_result = await self.aintellect_remove(
575
+ ai_result = await self.intellect_remove(
577
576
  input_data=input_data,
578
577
  output_format=output_format,
579
578
  prompt_id=prompt_id,
@@ -606,7 +605,7 @@ class AsyncIntel():
606
605
  return ai_result
607
606
 
608
607
 
609
- def aintellect_remove_warp(self,prompt_id: str):
608
+ def intellect_remove_warp(self,prompt_id: str):
610
609
  def outer_packing(func):
611
610
  @functools.wraps(func)
612
611
  async def wrapper(*args, **kwargs):
@@ -621,7 +620,7 @@ class AsyncIntel():
621
620
  elif isinstance(input_data,str):
622
621
  input_ = output_ = input_data
623
622
 
624
- output_ = await self.aintellect_remove_format(
623
+ output_ = await self.intellect_remove_format(
625
624
  input_data = input_data,
626
625
  prompt_id = prompt_id,
627
626
  OutputFormat = OutputFormat,
@@ -0,0 +1,529 @@
1
+ # 测试1
2
+
3
+ from pro_craft.utils import extract_
4
+ from pro_craft.log import Log
5
+ from pro_craft.database import Prompt, UseCase, PromptBase
6
+ from pro_craft.utils import create_session, create_async_session
7
+ from llmada.core import BianXieAdapter, ArkAdapter
8
+ from datetime import datetime
9
+ from enum import Enum
10
+ import functools
11
+ import json
12
+ import os
13
+ from sqlalchemy import create_engine
14
+ from pro_craft.database import SyncMetadata
15
+ import inspect
16
+ from pydantic import BaseModel, Field, ValidationError, field_validator
17
+ from datetime import datetime, timedelta
18
+ logger = Log.logger
19
+ editing_log = logger.debug
20
+
21
+ BATCH_SIZE = 1000
22
+
23
+ def get_last_sync_time(target_session) -> datetime:
24
+ """从目标数据库获取上次同步时间"""
25
+ metadata_entry = target_session.query(SyncMetadata).filter_by(table_name="sync_metadata").first()
26
+ if metadata_entry:
27
+ return metadata_entry.last_sync_time
28
+ return datetime(1970, 1, 1) # 默认一个很早的时间
29
+
30
+ def update_last_sync_time(target_session, new_sync_time: datetime):
31
+ """更新目标数据库的上次同步时间"""
32
+ metadata_entry = target_session.query(SyncMetadata).filter_by(table_name="sync_metadata").first()
33
+ if metadata_entry:
34
+ metadata_entry.last_sync_time = new_sync_time
35
+ else:
36
+ # 如果不存在,则创建
37
+ new_metadata = SyncMetadata(table_name="sync_metadata", last_sync_time=new_sync_time)
38
+ target_session.add(new_metadata)
39
+ target_session.commit()
40
+ print(f"Updated last sync time to: {new_sync_time}")
41
+
42
+
43
+
44
+ class IntellectType(Enum):
45
+ train = "train"
46
+ inference = "inference"
47
+ summary = "summary"
48
+
49
+ class Intel():
50
+ def __init__(self,
51
+ database_url = "",
52
+ model_name = "",
53
+ ):
54
+ database_url = database_url or os.getenv("database_url")
55
+ assert database_url
56
+ self.engine = create_engine(database_url, echo=False, # echo=True 仍然会打印所有执行的 SQL 语句
57
+ pool_size=10, # 连接池中保持的连接数
58
+ max_overflow=20, # 当pool_size不够时,允许临时创建的额外连接数
59
+ pool_recycle=3600, # 每小时回收一次连接
60
+ pool_pre_ping=True, # 使用前检查连接活性
61
+ pool_timeout=30 # 等待连接池中连接的最长时间(秒)
62
+ )
63
+
64
+ PromptBase.metadata.create_all(self.engine)
65
+
66
+ if model_name in ["gemini-2.5-flash-preview-05-20-nothinking",]:
67
+ self.llm = BianXieAdapter(model_name = model_name)
68
+ elif model_name in ["doubao-1-5-pro-256k-250115",]:
69
+ self.llm = ArkAdapter(model_name = model_name)
70
+ else:
71
+ print('Use BianXieAdapter')
72
+ self.llm = BianXieAdapter()
73
+
74
+
75
+ def _get_latest_prompt_version(self,target_prompt_id,session):
76
+ """
77
+ 获取指定 prompt_id 的最新版本数据,通过创建时间判断。
78
+ """
79
+
80
+ result = session.query(Prompt).filter(
81
+ Prompt.prompt_id == target_prompt_id
82
+ ).order_by(
83
+ Prompt.timestamp.desc(),
84
+ Prompt.version.desc()
85
+ ).first()
86
+
87
+ if result:
88
+ editing_log(f"找到 prompt_id '{target_prompt_id}' 的最新版本 (基于时间): {result.version}")
89
+ else:
90
+ editing_log(f"未找到 prompt_id '{target_prompt_id}' 的任何版本。")
91
+ return result
92
+
93
+ def _get_specific_prompt_version(self,target_prompt_id, target_version,session):
94
+ """
95
+ 获取指定 prompt_id 和特定版本的数据。
96
+
97
+ Args:
98
+ target_prompt_id (str): 目标提示词的唯一标识符。
99
+ target_version (int): 目标提示词的版本号。
100
+ table_name (str): 存储提示词数据的数据库表名。
101
+ db_manager (DBManager): 数据库管理器的实例,用于执行查询。
102
+
103
+ Returns:
104
+ dict or None: 如果找到,返回包含 id, prompt_id, version, timestamp, prompt 字段的字典;
105
+ 否则返回 None。
106
+ """
107
+
108
+ result = session.query(Prompt).filter(
109
+ Prompt.prompt_id == target_prompt_id,
110
+ Prompt.version == target_version
111
+ ).first() # 因为 (prompt_id, version) 是唯一的,所以 first() 足够
112
+ if result:
113
+ editing_log(f"找到 prompt_id '{target_prompt_id}', 版本 '{target_version}' 的提示词数据。")
114
+ else:
115
+ editing_log(f"未找到 prompt_id '{target_prompt_id}', 版本 '{target_version}' 的提示词数据。")
116
+ return result
117
+
118
+
119
+ def sync_prompt_data_to_database(self,database_url:str):
120
+ target_engine = create_engine(database_url, echo=False)
121
+ # PromptBase.metadata.create_all(target_engine,tables=[SyncMetadata.__table__])
122
+ PromptBase.metadata.create_all(target_engine)
123
+
124
+ with create_session(self.engine) as source_session:
125
+ with create_session(target_engine) as target_session:
126
+ last_sync_time = get_last_sync_time(target_session)
127
+ print(f"Starting sync for sync_metadata from: {last_sync_time}")
128
+
129
+
130
+ processed_count = 0
131
+ current_batch_max_updated_at = last_sync_time
132
+
133
+ while True:
134
+ records_to_sync = source_session.query(Prompt)\
135
+ .filter(Prompt.timestamp > last_sync_time)\
136
+ .order_by(Prompt.timestamp.asc(), Prompt.id.asc())\
137
+ .limit(BATCH_SIZE)\
138
+ .all()
139
+ if not records_to_sync:
140
+ break # 没有更多记录了
141
+
142
+ # 准备要插入或更新到目标数据库的数据
143
+ for record in records_to_sync:
144
+ # 查找目标数据库中是否存在该ID的记录
145
+ # 这里的 `User` 模型会对应到 target_db.users
146
+ target_prompt = target_session.query(Prompt).filter_by(id=record.id).first()
147
+
148
+ if target_prompt:
149
+ # 如果存在,则更新
150
+ target_prompt.prompt_id = record.prompt_id
151
+ target_prompt.version = record.version
152
+ target_prompt.timestamp = record.timestamp
153
+ target_prompt.prompt = record.prompt
154
+ target_prompt.use_case = record.use_case
155
+ target_prompt.action_type = record.action_type
156
+ target_prompt.demand = record.demand
157
+ target_prompt.score = record.score
158
+ target_prompt.is_deleted = record.is_deleted
159
+ else:
160
+ # 如果不存在,则添加新记录
161
+ # 注意:这里需要创建一个新的User实例,而不是直接添加源数据库的record对象
162
+ new_user = Prompt(
163
+ prompt_id=record.prompt_id,
164
+ version=record.version,
165
+ timestamp=record.timestamp,
166
+ prompt = record.prompt,
167
+ use_case = record.use_case,
168
+ action_type = record.action_type,
169
+ demand = record.demand,
170
+ score = record.score,
171
+ is_deleted = record.is_deleted
172
+ )
173
+ target_session.add(new_user)
174
+
175
+ # 记录当前批次最大的 updated_at
176
+ if record.timestamp > current_batch_max_updated_at:
177
+ current_batch_max_updated_at = record.timestamp
178
+
179
+ target_session.commit() # 提交当前批次的变更
180
+ processed_count += len(records_to_sync)
181
+ print(f"Processed {len(records_to_sync)} records. Total processed: {processed_count}")
182
+
183
+ # 更新 last_sync_time,为确保下次查询从正确的时间点开始,
184
+ # 可以使用当前批次中最大的 updated_at + 1微秒,以避免重复查询同一时间戳的记录。
185
+ # 更严谨的做法是,如果 updated_at 相同,则使用 ID 进行辅助排序,并记录 ID。
186
+ # 为了简化,这里直接使用 updated_at
187
+ last_sync_time = current_batch_max_updated_at + timedelta(microseconds=1)
188
+
189
+ if len(records_to_sync) < BATCH_SIZE: # 如果查询到的记录数小于批次大小,说明已经处理完所有符合条件的记录
190
+ break
191
+
192
+ if processed_count > 0:
193
+ # 最终更新last_sync_time到数据库,确保记录的是所有已处理记录中最新的一个
194
+ update_last_sync_time(target_session, current_batch_max_updated_at + timedelta(microseconds=1))
195
+ else:
196
+ print("No new records to sync.")
197
+
198
+
199
+ def get_prompts_from_sql(self,
200
+ prompt_id: str,
201
+ version = None,
202
+ session = None) -> Prompt:
203
+ """
204
+ 从sql获取提示词
205
+ """
206
+ # 查看是否已经存在
207
+ if version:
208
+ prompts_obj = self._get_specific_prompt_version(prompt_id,version,session=session)
209
+ if not prompts_obj:
210
+ prompts_obj = self._get_latest_prompt_version(prompt_id,session = session)
211
+ else:
212
+ prompts_obj = self._get_latest_prompt_version(prompt_id,session = session)
213
+ return prompts_obj
214
+
215
+
216
+ def save_prompt_increment_version(self,
217
+ prompt_id: str,
218
+ new_prompt: str,
219
+ use_case:str = "",
220
+ action_type = "inference",
221
+ demand = "",
222
+ score = 60,
223
+ session = None):
224
+ """
225
+ 从sql保存提示词
226
+ input_data 指的是输入用例, 可以为空
227
+ """
228
+ # 查看是否已经存在
229
+ prompts_obj = self.get_prompts_from_sql(prompt_id=prompt_id,session=session)
230
+
231
+ if prompts_obj:
232
+ # 如果存在版本加1
233
+ version_ori = prompts_obj.version
234
+ _, version = version_ori.split(".")
235
+ version = int(version)
236
+ version += 1
237
+ version_ = f"1.{version}"
238
+
239
+ else:
240
+ # 如果不存在版本为1.0
241
+ version_ = '1.0'
242
+
243
+ prompt1 = Prompt(prompt_id=prompt_id,
244
+ version=version_,
245
+ timestamp=datetime.now(),
246
+ prompt = new_prompt,
247
+ use_case = use_case,
248
+ action_type = action_type,
249
+ demand = demand,
250
+ score = score
251
+ )
252
+
253
+ session.add(prompt1)
254
+ session.commit() # 提交事务,将数据写入数据库
255
+
256
+ def save_use_case_by_sql(self,
257
+ prompt_id: str,
258
+ use_case:str = "",
259
+ output = "",
260
+ solution: str = "",
261
+ session = None
262
+ ):
263
+ """
264
+ 从sql保存提示词
265
+ """
266
+ use_case = UseCase(prompt_id=prompt_id,
267
+ use_case = use_case,
268
+ output = output,
269
+ solution = solution,
270
+ )
271
+
272
+ session.add(use_case)
273
+ session.commit() # 提交事务,将数据写入数据库
274
+
275
+ def summary_to_sql(
276
+ self,
277
+ prompt_id:str,
278
+ version = None,
279
+ prompt = "",
280
+ session = None
281
+ ):
282
+ """
283
+ 让大模型微调已经存在的 system_prompt
284
+ """
285
+ system_prompt_created_prompt = """
286
+ 很棒, 我们已经达成了某种默契, 我们之间合作无间, 但是, 可悲的是, 当我关闭这个窗口的时候, 你就会忘记我们之间经历的种种磨合, 这是可惜且心痛的, 所以你能否将目前这一套处理流程结晶成一个优质的prompt 这样, 我们下一次只要将prompt输入, 你就能想起我们今天的磨合过程,
287
+ 对了,我提示一点, 这个prompt的主角是你, 也就是说, 你在和未来的你对话, 你要教会未来的你今天这件事, 是否让我看懂到时其次
288
+
289
+ 只要输出提示词内容即可, 不需要任何的说明和解释
290
+ """
291
+ system_result = self.llm.product(prompt + system_prompt_created_prompt)
292
+
293
+ s_prompt = extract_(system_result,pattern_key=r"prompt")
294
+ chat_history = s_prompt or system_result
295
+ self.save_prompt_increment_version(prompt_id,
296
+ new_prompt = chat_history,
297
+ use_case = " summary ",
298
+ session = session)
299
+
300
+ def prompt_finetune_to_sql(
301
+ self,
302
+ prompt_id:str,
303
+ version = None,
304
+ demand: str = "",
305
+ session = None,
306
+ ):
307
+ """
308
+ 让大模型微调已经存在的 system_prompt
309
+ """
310
+ change_by_opinion_prompt = """
311
+ 你是一个资深AI提示词工程师,具备卓越的Prompt设计与优化能力。
312
+ 我将为你提供一段现有System Prompt。你的核心任务是基于这段Prompt进行修改,以实现我提出的特定目标和功能需求。
313
+ 请你绝对严格地遵循以下原则:
314
+ 极端最小化修改原则(核心):
315
+ 在满足所有功能需求的前提下,只进行我明确要求的修改。
316
+ 即使你认为有更“优化”、“清晰”或“简洁”的表达方式,只要我没有明确要求,也绝不允许进行任何未经指令的修改。
317
+ 目的就是尽可能地保留原有Prompt的字符和结构不变,除非我的功能要求必须改变。
318
+ 例如,如果我只要求你修改一个词,你就不应该修改整句话的结构。
319
+ 严格遵循我的指令:
320
+ 你必须精确地执行我提出的所有具体任务和要求。
321
+ 绝不允许自行添加任何超出指令范围的说明、角色扮演、约束条件或任何非我指令要求的内容。
322
+ 保持原有Prompt的风格和语调:
323
+ 尽可能地与现有Prompt的语言风格、正式程度和语调保持一致。
324
+ 不要改变不相关的句子或其表达方式。
325
+ 只提供修改后的Prompt:
326
+ 直接输出修改后的完整System Prompt文本。
327
+ 不要包含任何解释、说明或额外对话。
328
+ 在你开始之前,请务必确认你已理解并能绝对严格地遵守这些原则。任何未经明确指令的改动都将视为未能完成任务。
329
+
330
+ 现有System Prompt:
331
+ {old_system_prompt}
332
+
333
+ 功能需求:
334
+ {opinion}
335
+ """
336
+ prompts_obj = self.get_prompts_from_sql(prompt_id = prompt_id,version = version,session = session)
337
+
338
+ if demand:
339
+ new_prompt = self.llm.product(
340
+ change_by_opinion_prompt.format(old_system_prompt=prompts_obj.prompt, opinion=demand)
341
+ )
342
+ else:
343
+ new_prompt = prompts_obj.prompt
344
+ self.save_prompt_increment_version(prompt_id = prompt_id,
345
+ new_prompt = new_prompt,
346
+ use_case = " finetune ",
347
+ session = session)
348
+
349
+ def push_action_order(self,
350
+ prompt_id: str,
351
+ demand : str,
352
+ action_type = 'train'):
353
+
354
+ """
355
+ 从sql保存提示词
356
+ 推一个train 状态到指定的位置
357
+
358
+ 将打算修改的状态推上数据库 # 1
359
+ """
360
+ # 查看是否已经存在
361
+ with create_session(self.engine) as session:
362
+ latest_prompt = self.get_prompts_from_sql(prompt_id=prompt_id,session=session)
363
+
364
+ self.save_prompt_increment_version(prompt_id=latest_prompt.prompt_id,
365
+ new_prompt = latest_prompt.prompt,
366
+ use_case = latest_prompt.use_case,
367
+ action_type=action_type,
368
+ demand=demand,
369
+ score=latest_prompt.score,
370
+ session=session
371
+ )
372
+
373
+ return "success"
374
+
375
+
376
+ def intellect_remove(self,
377
+ input_data: dict | str,
378
+ output_format: str,
379
+ prompt_id: str,
380
+ version: str = None,
381
+ inference_save_case = True,
382
+ push_patch = False,
383
+ ):
384
+ """
385
+ # output_format 单独使用一个大模型处理
386
+ 使用指南:
387
+ 1 训练, 使用单一例子做大量的沟通来奠定基础
388
+ 2 总结, 将沟通好的总结成完整提示词
389
+ 3 推理, 使用部署
390
+ 4 微调, 针对一些格式性的, 问题进行微调
391
+ 5 补丁, 微调无法解决的问题, 可以尝试使用补丁来解决
392
+ """
393
+ if isinstance(input_data,dict):
394
+ input_ = json.dumps(input_data,ensure_ascii=False)
395
+ elif isinstance(input_data,str):
396
+ input_ = input_data
397
+
398
+
399
+ # 查数据库, 获取最新提示词对象
400
+ with create_session(self.engine) as session:
401
+ result_obj = self.get_prompts_from_sql(prompt_id=prompt_id,session=session)
402
+
403
+ prompt = result_obj.prompt
404
+ if result_obj.action_type == "inference":
405
+ # 直接推理即可
406
+ ai_result = self.llm.product(prompt + "\n-----input----\n" + input_)
407
+ if inference_save_case:
408
+ self.save_use_case_by_sql(prompt_id,
409
+ use_case = input_,
410
+ output = ai_result,
411
+ solution = "备注/理想回复",
412
+ session = session,
413
+ )
414
+
415
+ elif result_obj.action_type == "train":
416
+ assert result_obj.demand # 如果type = train 且 demand 是空 则报错
417
+ # 则训练推广
418
+
419
+ # 新版本 默人修改会 inference 状态
420
+ chat_history = prompt
421
+ before_input = result_obj.use_case
422
+ demand = result_obj.demand
423
+
424
+
425
+ assert demand
426
+ # 注意, 这里的调整要求使用最初的那个输入, 最好一口气调整好
427
+ chat_history = prompt
428
+ if input_ == before_input: # 输入没变, 说明还是针对同一个输入进行讨论
429
+ # input_prompt = chat_history + "\nuser:" + demand
430
+ input_prompt = chat_history + "\nuser:" + demand
431
+ else:
432
+ # input_prompt = chat_history + "\nuser:" + demand + "\n-----input----\n" + input_
433
+ input_prompt = chat_history + "\nuser:" + demand + "\n-----input----\n" + input_
434
+
435
+ ai_result = self.llm.product(input_prompt)
436
+ chat_history = input_prompt + "\nassistant:\n" + ai_result # 用聊天记录作为完整提示词
437
+ self.save_prompt_increment_version(prompt_id, chat_history,
438
+ use_case = input_,
439
+ score = 60,
440
+ session = session)
441
+
442
+ elif result_obj.action_type == "summary":
443
+ self.summary_to_sql(prompt_id = prompt_id,
444
+ prompt = prompt,
445
+ session = session
446
+ )
447
+ ai_result = self.llm.product(prompt + "\n-----input----\n" + input_)
448
+
449
+ elif result_obj.action_type == "finetune":
450
+ demand = result_obj.demand
451
+
452
+ assert demand
453
+ self.prompt_finetune_to_sql(prompt_id = prompt_id,
454
+ demand = demand,
455
+ session = session
456
+ )
457
+ ai_result = self.llm.product(prompt + "\n-----input----\n" + input_)
458
+ elif result_obj.action_type == "patch":
459
+
460
+ demand = result_obj.demand
461
+ assert demand
462
+
463
+ chat_history = prompt + demand
464
+ ai_result = self.llm.product(chat_history + "\n-----input----\n" + input_)
465
+ if push_patch:
466
+ self.save_prompt_increment_version(prompt_id, chat_history,
467
+ use_case = input_,
468
+ score = 60,
469
+ session = session)
470
+ else:
471
+ raise
472
+
473
+ system_prompt = """
474
+ 对数据的数据,进行整理, 不改变其文本内容, 只将其整合成特定的形式
475
+ """
476
+ ai_result = self.llm.product(system_prompt + ai_result + output_format)
477
+
478
+ return ai_result
479
+
480
+
481
+ def intellect_remove_format(self,
482
+ input_data: dict | str,
483
+ prompt_id: str,
484
+ OutputFormat: object = None,
485
+ ExtraFormats: list[object] = [],
486
+ version: str = None,
487
+ inference_save_case = True,
488
+ ):
489
+
490
+ if OutputFormat:
491
+ base_format_prompt = """
492
+ 按照一定格式输出, 以便可以通过如下校验
493
+
494
+ 使用以下正则检出
495
+ "```json([\s\S]*?)```"
496
+ 使用以下方式验证
497
+ """
498
+ output_format = base_format_prompt + "\n".join([inspect.getsource(outputformat) for outputformat in ExtraFormats]) + inspect.getsource(OutputFormat)
499
+
500
+ else:
501
+ output_format = ""
502
+
503
+ ai_result = self.intellect_remove(
504
+ input_data=input_data,
505
+ output_format=output_format,
506
+ prompt_id=prompt_id,
507
+ version=version,
508
+ inference_save_case=inference_save_case
509
+ )
510
+
511
+ if OutputFormat:
512
+ try:
513
+ ai_result = json.loads(extract_(ai_result,r'json'))
514
+ OutputFormat(**ai_result)
515
+ except ValidationError as e:
516
+ log_ = "记忆卡片合并 - 大模型生成的格式未通过校验"
517
+ logger.error(log_)
518
+ logger.error(f"错误类型: {type(e)}")
519
+ logger.error(f"错误信息: {e}")
520
+ logger.error(f"错误详情 (errors()): {e.errors()}")
521
+ logger.error(f"错误详情 (json()): {e.json(indent=2)}")
522
+ raise ValidationError(log_)
523
+ else:
524
+ try:
525
+ assert isinstance(ai_result,str)
526
+ except AssertionError as e:
527
+ logger.error("错误了问题")
528
+
529
+ return ai_result
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pro-craft
3
- Version: 0.1.10
3
+ Version: 0.1.12
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.12
6
6
  Description-Content-Type: text/markdown
@@ -4,8 +4,9 @@ pro_craft/designer.py,sha256=3gyCqrjcw61sHzDjUPKhL1LOAE8xWLLbNT8NlK2mFLc,4739
4
4
  pro_craft/evals.py,sha256=1T86jur4k3cLk43j1GyAW4JS0nPNfl6P0ZOQmu-SgpA,1928
5
5
  pro_craft/file_manager.py,sha256=2j7lCt9L4mtvAy8_76ibTthXLwKKmVatWIB3DSvQM7U,3805
6
6
  pro_craft/log.py,sha256=MZf9jCZsiRoAq8v4FxVnJqeSXxgzAiiKf7mxz6bFtwM,4263
7
- pro_craft/prompt_helper.py,sha256=1EDGP2sKoUCrLXiR0kD2AqzT9LcFYWO8S2FyaZlBoxc,26150
8
- pro_craft/prompt_helper_async.py,sha256=Ej0JXwev0FmPSoOE5iEXtZxQ3pXoqcaulyyUuC7WyC4,27859
7
+ pro_craft/prompt_helper.py,sha256=GClPsomdGdo6FXlp8VdiQy8GaBtj3oLeq2oFw0RiM3k,26592
8
+ pro_craft/prompt_helper_async.py,sha256=-EtwjDUL2Xoi4qjZpzgnUyAVBkt-WCocGgVl5PgA4Js,27771
9
+ pro_craft/prompt_helper_new.py,sha256=DV871XElJmHDO2xis1mC1f3QFvq3ll81VGGD9aj0Eiw,23542
9
10
  pro_craft/server.py,sha256=fPAosQIU0d7gxICiALl8u6QwbLI4cawVFyoRYebRES0,2827
10
11
  pro_craft/utils.py,sha256=cpvwk68mD9hYY8WCq2JXzfrrXqpshiscz_OSav4tC7U,5687
11
12
  pro_craft/code_helper/coder.py,sha256=NXglF1KiPtGe4HZN0MZvFJ8p9Iyd5kzIt72DQGgRwXA,24715
@@ -17,7 +18,7 @@ pro_craft/server/mcp/math.py,sha256=OOzGXx64nK4bOVlu33PtVddcCQ9ilqA3Em9yxjSX9cg,
17
18
  pro_craft/server/mcp/resource.py,sha256=z94jP3qZofO-1lZCM3TuOfLajw41HARs1ojXab1ymas,776
18
19
  pro_craft/server/mcp/weather.py,sha256=RAGuf4sgjlTQSfRRZ1Fo18JnuMQRS_Db9p6AqBQrl8E,455
19
20
  pro_craft/server/router/recommended.py,sha256=IAZFdmb8HSl2_TOJeuv5uOKIX47XyX4p4sEwxG-0vt0,9968
20
- pro_craft-0.1.10.dist-info/METADATA,sha256=d0eKMauNY8YEx9A8ZAtIvGXEVYTER04UwYCscH7ifHY,1800
21
- pro_craft-0.1.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
22
- pro_craft-0.1.10.dist-info/top_level.txt,sha256=yqYDHArnYMWpeCxkmGRwlL6sJtxiOUnYylLDx9EOgFg,10
23
- pro_craft-0.1.10.dist-info/RECORD,,
21
+ pro_craft-0.1.12.dist-info/METADATA,sha256=VKEqBoEWYaOP0Ue2BSZ3iKZ1W_MYqsaRS7f3lQ-bscs,1800
22
+ pro_craft-0.1.12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
23
+ pro_craft-0.1.12.dist-info/top_level.txt,sha256=yqYDHArnYMWpeCxkmGRwlL6sJtxiOUnYylLDx9EOgFg,10
24
+ pro_craft-0.1.12.dist-info/RECORD,,