pro-craft 0.1.29__tar.gz → 0.1.30__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 pro-craft might be problematic. Click here for more details.

Files changed (28) hide show
  1. {pro_craft-0.1.29 → pro_craft-0.1.30}/PKG-INFO +1 -1
  2. {pro_craft-0.1.29 → pro_craft-0.1.30}/pyproject.toml +1 -1
  3. {pro_craft-0.1.29 → pro_craft-0.1.30}/src/pro_craft/database.py +4 -4
  4. pro_craft-0.1.30/src/pro_craft/prompt_craft/async_ copy.py +985 -0
  5. {pro_craft-0.1.29 → pro_craft-0.1.30}/src/pro_craft.egg-info/PKG-INFO +1 -1
  6. {pro_craft-0.1.29 → pro_craft-0.1.30}/src/pro_craft.egg-info/SOURCES.txt +1 -0
  7. {pro_craft-0.1.29 → pro_craft-0.1.30}/README.md +0 -0
  8. {pro_craft-0.1.29 → pro_craft-0.1.30}/setup.cfg +0 -0
  9. {pro_craft-0.1.29 → pro_craft-0.1.30}/src/pro_craft/__init__.py +0 -0
  10. {pro_craft-0.1.29 → pro_craft-0.1.30}/src/pro_craft/code_helper/coder.py +0 -0
  11. {pro_craft-0.1.29 → pro_craft-0.1.30}/src/pro_craft/code_helper/designer.py +0 -0
  12. {pro_craft-0.1.29 → pro_craft-0.1.30}/src/pro_craft/file_manager.py +0 -0
  13. {pro_craft-0.1.29 → pro_craft-0.1.30}/src/pro_craft/log.py +0 -0
  14. {pro_craft-0.1.29 → pro_craft-0.1.30}/src/pro_craft/prompt_craft/__init__.py +0 -0
  15. {pro_craft-0.1.29 → pro_craft-0.1.30}/src/pro_craft/prompt_craft/async_.py +0 -0
  16. {pro_craft-0.1.29 → pro_craft-0.1.30}/src/pro_craft/prompt_craft/new.py +0 -0
  17. {pro_craft-0.1.29 → pro_craft-0.1.30}/src/pro_craft/prompt_craft/sync.py +0 -0
  18. {pro_craft-0.1.29 → pro_craft-0.1.30}/src/pro_craft/server/mcp/__init__.py +0 -0
  19. {pro_craft-0.1.29 → pro_craft-0.1.30}/src/pro_craft/server/mcp/prompt.py +0 -0
  20. {pro_craft-0.1.29 → pro_craft-0.1.30}/src/pro_craft/server/router/__init__.py +0 -0
  21. {pro_craft-0.1.29 → pro_craft-0.1.30}/src/pro_craft/server/router/prompt.py +0 -0
  22. {pro_craft-0.1.29 → pro_craft-0.1.30}/src/pro_craft/utils.py +0 -0
  23. {pro_craft-0.1.29 → pro_craft-0.1.30}/src/pro_craft.egg-info/dependency_links.txt +0 -0
  24. {pro_craft-0.1.29 → pro_craft-0.1.30}/src/pro_craft.egg-info/requires.txt +0 -0
  25. {pro_craft-0.1.29 → pro_craft-0.1.30}/src/pro_craft.egg-info/top_level.txt +0 -0
  26. {pro_craft-0.1.29 → pro_craft-0.1.30}/tests/test22.py +0 -0
  27. {pro_craft-0.1.29 → pro_craft-0.1.30}/tests/test_coder.py +0 -0
  28. {pro_craft-0.1.29 → pro_craft-0.1.30}/tests/test_designer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pro-craft
3
- Version: 0.1.29
3
+ Version: 0.1.30
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.12
6
6
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pro-craft"
3
- version = "0.1.29"
3
+ version = "0.1.30"
4
4
  description = "Add your description here"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -179,10 +179,10 @@ class Prompt(PromptBase):
179
179
  class UseCase(PromptBase):
180
180
  __tablename__ = 'ai_usecase' # 数据库中的表名,你可以改成你希望的名字
181
181
 
182
- __table_args__ = (
183
- UniqueConstraint('prompt_id', 'use_case', name='_prompt_id_version_uc'),
184
- # 'name' 参数是可选的,用于给数据库中的约束指定一个名称,方便管理和调试
185
- )
182
+ # __table_args__ = (
183
+ # UniqueConstraint('prompt_id', 'use_case', name='_prompt_id_version_uc'),
184
+ # # 'name' 参数是可选的,用于给数据库中的约束指定一个名称,方便管理和调试
185
+ # )
186
186
 
187
187
  # id (int, primary_key=True, autoincrement=True)
188
188
  # 你的属性表中 id 为 int, true (not null), true (primary key), 0 (length), ASC (key order), true (auto increment)
@@ -0,0 +1,985 @@
1
+ # 测试1
2
+ from pro_craft.utils import extract_
3
+ from pro_craft import logger as pro_craft_logger
4
+ from llmada.core import BianXieAdapter, ArkAdapter
5
+ from datetime import datetime
6
+ from enum import Enum
7
+ import functools
8
+ import json
9
+ import os
10
+ from pro_craft.database import Prompt, UseCase, PromptBase
11
+ from pro_craft.utils import create_session, create_async_session
12
+ from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine # 异步核心
13
+ from sqlalchemy import select, delete # 导入 select, delete 用于异步操作
14
+ import inspect
15
+ from datetime import datetime
16
+ from pro_craft.utils import extract_
17
+ import asyncio
18
+ import re
19
+ from pydantic import BaseModel, ValidationError, field_validator
20
+ from sqlalchemy import select, desc
21
+ from json.decoder import JSONDecodeError
22
+ from pro_craft.database import SyncMetadata
23
+ from datetime import datetime, timedelta
24
+ from datetime import datetime, timedelta
25
+ from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker
26
+ from sqlalchemy import select, and_ # 引入 select 和 and_
27
+ from sqlalchemy.orm import class_mapper # 用于检查对象是否是持久化的
28
+
29
+
30
+ class IntellectRemoveFormatError(Exception):
31
+ pass
32
+
33
+ class IntellectRemoveError(Exception):
34
+ pass
35
+
36
+ BATCH_SIZE = 100
37
+ MIN_SUCCESS_RATE = 00.0 # 这里定义通过阈值, 高于该比例则通过
38
+
39
+
40
+ def slog(s, target: str = "target",logger = None):
41
+ COLOR_GREEN = "\033[92m"
42
+ COLOR_RESET = "\033[0m" # 重置颜色
43
+ logger("\n"+f"{COLOR_GREEN}=={COLOR_RESET}" * 50)
44
+ logger(target + "\n "+"--" * 40)
45
+ logger(type(s))
46
+ logger(s)
47
+ logger("\n"+f"{COLOR_GREEN}=={COLOR_RESET}" * 50)
48
+
49
+ def fix_broken_json_string(broken_json_str):
50
+ # 移除 BOM
51
+ broken_json_str = broken_json_str.lstrip('\ufeff')
52
+ # 移除大部分非法 ASCII 控制字符
53
+ broken_json_str = re.sub(r'[\x00-\x08\x0b\x0c\x0e-\x1f]', '', broken_json_str)
54
+
55
+ # 尝试找到 "content": " 和它对应的结束 "
56
+ # 这是一个挑战,因为中间有未转义的换行。
57
+ # 我们会寻找 "content": ",然后捕获从那以后直到最后一个 " 的所有内容,并替换其中的裸换行。
58
+
59
+ # 注意:这个正则假设 "content" 的值是最后一个键值对,并且直到字符串末尾的 " 才结束
60
+ # 并且假设其他字段都是合法的单行字符串
61
+ fixed_json_str = re.sub(
62
+ r'("content":\s*")(.+?)"\s*}', # 匹配 "content": ",然后捕获所有内容直到最后一个 " }
63
+ lambda m: m.group(1) + m.group(2).replace('\n', '\\n').replace('\r', '\\r') + '"\n}',
64
+ broken_json_str,
65
+ flags=re.DOTALL # 允许 . 匹配换行
66
+ )
67
+
68
+ # 修正可能的最后一行丢失的 }
69
+ if not fixed_json_str.strip().endswith('}'):
70
+ fixed_json_str += '\n}' # 补上结束的 }
71
+
72
+ return fixed_json_str
73
+
74
+
75
+ # def get_last_sync_time(target_session) -> datetime:
76
+ # """从目标数据库获取上次同步时间"""
77
+ # metadata_entry = target_session.query(SyncMetadata).filter_by(table_name="sync_metadata").first()
78
+ # if metadata_entry:
79
+ # return metadata_entry.last_sync_time
80
+ # return datetime(1970, 1, 1) # 默认一个很早的时间
81
+
82
+ # def update_last_sync_time(target_session, new_sync_time: datetime):
83
+ # """更新目标数据库的上次同步时间"""
84
+ # metadata_entry = target_session.query(SyncMetadata).filter_by(table_name="sync_metadata").first()
85
+ # if metadata_entry:
86
+ # metadata_entry.last_sync_time = new_sync_time
87
+ # else:
88
+ # # 如果不存在,则创建
89
+ # new_metadata = SyncMetadata(table_name="sync_metadata", last_sync_time=new_sync_time)
90
+ # target_session.add(new_metadata)
91
+ # target_session.commit()
92
+ # print(f"Updated last sync time to: {new_sync_time}")
93
+
94
+
95
+ async def get_last_sync_time(target_session: AsyncSession) -> datetime:
96
+ """从目标数据库获取上次同步时间"""
97
+ # 修正点:使用 select() 和 execute()
98
+ result = await target_session.execute(
99
+ select(SyncMetadata).filter_by(table_name="ai_sync_metadata")
100
+ )
101
+ metadata_entry = result.scalar_one_or_none() # 获取单个对象或 None
102
+
103
+ if metadata_entry:
104
+ return metadata_entry.last_sync_time
105
+ return datetime(1970, 1, 1) # 默认一个很早的时间
106
+
107
+
108
+ # from your_module import SyncMetadata # 假设 SyncMetadata 已导入
109
+ # from sqlalchemy import select # 确保引入 select
110
+
111
+ async def update_last_sync_time(target_session: AsyncSession, new_sync_time: datetime):
112
+ """更新目标数据库的上次同步时间"""
113
+ # 修正点:使用 select() 和 execute()
114
+ result = await target_session.execute(
115
+ select(SyncMetadata).filter_by(table_name="ai_sync_metadata")
116
+ )
117
+ metadata_entry = result.scalar_one_or_none()
118
+
119
+ if metadata_entry:
120
+ metadata_entry.last_sync_time = new_sync_time
121
+ else:
122
+ # 如果不存在,则创建
123
+ new_metadata = SyncMetadata(table_name="ai_sync_metadata", last_sync_time=new_sync_time)
124
+ target_session.add(new_metadata)
125
+
126
+ # 异步提交事务
127
+ await target_session.commit() # TODO
128
+ print(f"Updated last sync time to: {new_sync_time}")
129
+
130
+
131
+
132
+
133
+
134
+
135
+ class IntellectType(Enum):
136
+ train = "train"
137
+ inference = "inference"
138
+ summary = "summary"
139
+
140
+ class AsyncIntel():
141
+ def __init__(self,
142
+ database_url = "",
143
+ model_name = "",
144
+ logger = None,
145
+ ):
146
+ database_url = database_url or os.getenv("database_url")
147
+ self.logger = logger or pro_craft_logger
148
+ try:
149
+ assert database_url
150
+ assert 'aio' in database_url
151
+ except AssertionError as e:
152
+ slog(database_url,'database_url',logger=self.logger.warning)
153
+ raise IntellectRemoveFormatError(f"异步服务url必须提供, 且必须是aiomysql配置") from e
154
+
155
+ self.engine = create_async_engine(database_url, echo=False,
156
+ pool_size=10, # 连接池中保持的连接数
157
+ max_overflow=20, # 当pool_size不够时,允许临时创建的额外连接数
158
+ pool_recycle=3600, # 每小时回收一次连接
159
+ pool_pre_ping=True, # 使用前检查连接活性
160
+ pool_timeout=30 # 等待连接池中连接的最长时间(秒)
161
+ )
162
+
163
+ if model_name in ["gemini-2.5-flash-preview-05-20-nothinking",]:
164
+ self.llm = BianXieAdapter(model_name = model_name)
165
+ elif model_name in ["doubao-1-5-pro-256k-250115",]:
166
+ self.llm = ArkAdapter(model_name = model_name)
167
+ else:
168
+ print('Use BianXieAdapter')
169
+ self.llm = BianXieAdapter()
170
+
171
+ async def create_specific_database(self):
172
+ tables_to_create_names = ["ai_prompts","ai_usecase"]
173
+ async with self.engine.begin() as conn:
174
+ # 从 metadata 中获取对应的 Table 对象
175
+ specific_database_objects = []
176
+ for table_name in tables_to_create_names:
177
+ if table_name in PromptBase.metadata.tables:
178
+ specific_database_objects.append(PromptBase.metadata.tables[table_name])
179
+ else:
180
+ print(f"Warning: Table '{table_name}' not found in metadata.")
181
+
182
+ if specific_database_objects:
183
+ await conn.run_sync(PromptBase.metadata.create_all, tables=specific_database_objects)
184
+ else:
185
+ print("No specific tables to create.")
186
+
187
+ async def create_database(self,engine):
188
+ async with engine.begin() as conn:
189
+ await conn.run_sync(PromptBase.metadata.create_all)
190
+
191
+ async def _get_latest_prompt_version(self,target_prompt_id,session):
192
+ """
193
+ 获取指定 prompt_id 的最新版本数据,通过创建时间判断。
194
+ """
195
+ stmt = select(Prompt).filter(
196
+ Prompt.prompt_id == target_prompt_id
197
+ ).order_by(
198
+ desc(Prompt.timestamp), # 使用 sqlalchemy.desc() 来指定降序
199
+ desc(Prompt.version) # 使用 sqlalchemy.desc() 来指定降序
200
+ )
201
+
202
+ result = await session.execute(stmt)
203
+ # 3. 从 Result 对象中获取第一个模型实例
204
+ # .scalars() 用于从结果行中获取第一个列的值(这里是Prompt对象本身)
205
+ # .first() 获取第一个结果
206
+ result = result.scalars().first()
207
+
208
+ return result
209
+
210
+ async def _get_specific_prompt_version(self,target_prompt_id, target_version,session):
211
+ """
212
+ 获取指定 prompt_id 和特定版本的数据。
213
+
214
+ Args:
215
+ target_prompt_id (str): 目标提示词的唯一标识符。
216
+ target_version (int): 目标提示词的版本号。
217
+ table_name (str): 存储提示词数据的数据库表名。
218
+ db_manager (DBManager): 数据库管理器的实例,用于执行查询。
219
+
220
+ Returns:
221
+ dict or None: 如果找到,返回包含 id, prompt_id, version, timestamp, prompt 字段的字典;
222
+ 否则返回 None。
223
+ """
224
+ stmt = select(Prompt).filter(
225
+ Prompt.prompt_id == target_prompt_id,
226
+ Prompt.version == target_version
227
+ )
228
+ result = await session.execute(stmt)
229
+
230
+ specific_prompt = result.scalars().one_or_none()
231
+
232
+ return specific_prompt
233
+
234
+ async def sync_prompt_data_to_database(self,database_url:str):
235
+ target_engine = create_async_engine(database_url, echo=False)
236
+ await self.create_database(target_engine)
237
+ async with create_async_session(self.engine) as source_session:
238
+ async with create_async_session(target_engine) as target_session:
239
+
240
+ last_sync_time = await get_last_sync_time(target_session)
241
+ print(f"Starting sync for sync_metadata from: {last_sync_time}")
242
+
243
+
244
+ processed_count = 0
245
+ #2 next_sync_watermark = last_sync_time
246
+ current_batch_max_updated_at = last_sync_time
247
+
248
+ while True:
249
+ source_results = await source_session.execute(
250
+ select(Prompt)
251
+ .filter(Prompt.timestamp > last_sync_time)
252
+ .order_by(Prompt.timestamp.asc(), Prompt.id.asc())
253
+ .limit(BATCH_SIZE)
254
+ )
255
+ records_to_sync = source_results.scalars().all()
256
+ if not records_to_sync:
257
+ print("没有更多记录了")
258
+ break # 没有更多记录了
259
+
260
+ #2 max_timestamp_in_batch = datetime(1970, 1, 1) # 初始化为最早时间
261
+
262
+ # 准备要插入或更新到目标数据库的数据
263
+ for record in records_to_sync:
264
+ # 查找目标数据库中是否存在该ID的记录
265
+ # 这里的 `User` 模型会对应到 target_db.users
266
+ target_prompt_result = await target_session.execute(
267
+ select(Prompt).filter_by(id=record.id) # 假设 prompt_id 是唯一标识符
268
+ )
269
+ target_prompt = target_prompt_result.scalar_one_or_none()
270
+
271
+ if target_prompt:
272
+ # 如果存在,则更新
273
+ target_prompt.prompt_id = record.prompt_id
274
+ target_prompt.version = record.version
275
+ target_prompt.timestamp = record.timestamp
276
+ target_prompt.prompt = record.prompt
277
+ target_prompt.use_case = record.use_case
278
+ target_prompt.action_type = record.action_type
279
+ target_prompt.demand = record.demand
280
+ target_prompt.score = record.score
281
+ target_prompt.is_deleted = record.is_deleted
282
+ else:
283
+ # 如果不存在,则添加新记录
284
+ # 注意:这里需要创建一个新的User实例,而不是直接添加源数据库的record对象
285
+ new_prompt = Prompt(
286
+ prompt_id=record.prompt_id,
287
+ version=record.version,
288
+ timestamp=record.timestamp,
289
+ prompt = record.prompt,
290
+ use_case = record.use_case,
291
+ action_type = record.action_type,
292
+ demand = record.demand,
293
+ score = record.score,
294
+ is_deleted = record.is_deleted
295
+ )
296
+ target_session.add(new_prompt)
297
+
298
+ # 记录当前批次最大的 updated_at
299
+ #2
300
+ # if record.timestamp > max_timestamp_in_batch:
301
+ # max_timestamp_in_batch = record.timestamp
302
+ if record.timestamp > current_batch_max_updated_at:
303
+ current_batch_max_updated_at = record.timestamp
304
+
305
+
306
+ await target_session.commit()
307
+ processed_count += len(records_to_sync)
308
+ print(f"Processed {len(records_to_sync)} records. Total processed: {processed_count}")
309
+
310
+ #2 next_sync_watermark = max_timestamp_in_batch + timedelta(microseconds=1)
311
+ last_sync_time = current_batch_max_updated_at + timedelta(microseconds=1)
312
+
313
+
314
+ if len(records_to_sync) < BATCH_SIZE: # 如果查询到的记录数小于批次大小,说明已经处理完所有符合条件的记录
315
+ break
316
+
317
+ if processed_count > 0:
318
+ # 最终更新last_sync_time到数据库,确保记录的是所有已处理记录中最新的一个
319
+ await update_last_sync_time(target_session, current_batch_max_updated_at + timedelta(microseconds=1))
320
+
321
+ #2 await update_last_sync_time(target_session, next_sync_watermark)
322
+
323
+ await target_session.commit() # 确保最终的 metadata 更新也被提交
324
+ else:
325
+ print("No new records to sync.")
326
+
327
+
328
+ async def get_prompts_from_sql(self,
329
+ prompt_id: str,
330
+ version = None,
331
+ session = None) -> Prompt:
332
+ """
333
+ 从sql获取提示词
334
+ """
335
+ # 查看是否已经存在
336
+ if version:
337
+ prompts_obj = await self._get_specific_prompt_version(prompt_id,version,session=session)
338
+ if not prompts_obj:
339
+ prompts_obj = await self._get_latest_prompt_version(prompt_id,session = session)
340
+ else:
341
+ prompts_obj = await self._get_latest_prompt_version(prompt_id,session = session)
342
+ return prompts_obj
343
+
344
+
345
+ async def save_prompt_increment_version(self,
346
+ prompt_id: str,
347
+ new_prompt: str,
348
+ use_case:str = "",
349
+ action_type = "inference",
350
+ demand = "",
351
+ score = 60,
352
+ session = None):
353
+ """
354
+ 从sql保存提示词
355
+ input_data 指的是输入用例, 可以为空
356
+ """
357
+ # 查看是否已经存在
358
+ prompts_obj = await self.get_prompts_from_sql(prompt_id=prompt_id,session=session)
359
+
360
+ if prompts_obj:
361
+ # 如果存在版本加1
362
+ version_ori = prompts_obj.version
363
+ _, version = version_ori.split(".")
364
+ version = int(version)
365
+ version += 1
366
+ version_ = f"1.{version}"
367
+
368
+ else:
369
+ # 如果不存在版本为1.0
370
+ version_ = '1.0'
371
+
372
+ prompt1 = Prompt(prompt_id=prompt_id,
373
+ version=version_,
374
+ timestamp=datetime.now(),
375
+ prompt = new_prompt,
376
+ use_case = use_case,
377
+ action_type = action_type,
378
+ demand = demand,
379
+ score = score
380
+ )
381
+
382
+ session.add(prompt1)
383
+ await session.commit() # 提交事务,将数据写入数据库
384
+
385
+ async def get_use_case_by_sql(self,
386
+ target_prompt_id: str,
387
+ session = None
388
+ ):
389
+ """
390
+ 从sql保存提示词
391
+ """
392
+ stmt = select(UseCase).filter(UseCase.is_deleted == 0,
393
+ UseCase.prompt_id == target_prompt_id)
394
+
395
+ result = await session.execute(stmt)
396
+ # use_case = result.scalars().one_or_none()
397
+ use_case = result.scalars().all()
398
+ return use_case
399
+
400
+ async def save_use_case_by_sql(self,
401
+ prompt_id: str,
402
+ use_case:str = "",
403
+ output = "",
404
+ solution: str = "",
405
+ session = None
406
+ ):
407
+ """
408
+ 从sql保存提示词
409
+ """
410
+ #TODO 存之前保证数据库中相同的prompt_id中没有重复的use_case
411
+
412
+ use_case = UseCase(prompt_id=prompt_id,
413
+ use_case = use_case,
414
+ output = output,
415
+ solution = solution,
416
+ )
417
+
418
+ session.add(use_case)
419
+ await session.commit() # 提交事务,将数据写入数据库
420
+
421
+ async def summary_to_sql(
422
+ self,
423
+ prompt_id:str,
424
+ version = None,
425
+ prompt = "",
426
+ session = None
427
+ ):
428
+ """
429
+ 让大模型微调已经存在的 system_prompt
430
+ """
431
+ system_prompt_created_prompt = """
432
+ 很棒, 我们已经达成了某种默契, 我们之间合作无间, 但是, 可悲的是, 当我关闭这个窗口的时候, 你就会忘记我们之间经历的种种磨合, 这是可惜且心痛的, 所以你能否将目前这一套处理流程结晶成一个优质的prompt 这样, 我们下一次只要将prompt输入, 你就能想起我们今天的磨合过程,
433
+ 对了,我提示一点, 这个prompt的主角是你, 也就是说, 你在和未来的你对话, 你要教会未来的你今天这件事, 是否让我看懂到时其次
434
+
435
+ 只要输出提示词内容即可, 不需要任何的说明和解释
436
+ """
437
+ system_result = await self.llm.aproduct(prompt + system_prompt_created_prompt)
438
+
439
+ s_prompt = extract_(system_result,pattern_key=r"prompt")
440
+ chat_history = s_prompt or system_result
441
+ await self.save_prompt_increment_version(prompt_id,
442
+ new_prompt = chat_history,
443
+ use_case = "",
444
+ score = 60,
445
+ session = session)
446
+
447
+ async def prompt_finetune_to_sql(
448
+ self,
449
+ prompt_id:str,
450
+ version = None,
451
+ demand: str = "",
452
+ session = None,
453
+ ):
454
+ """
455
+ 让大模型微调已经存在的 system_prompt
456
+ """
457
+ change_by_opinion_prompt = """
458
+ 你是一个资深AI提示词工程师,具备卓越的Prompt设计与优化能力。
459
+ 我将为你提供一段现有System Prompt。你的核心任务是基于这段Prompt进行修改,以实现我提出的特定目标和功能需求。
460
+ 请你绝对严格地遵循以下原则:
461
+ 极端最小化修改原则(核心):
462
+ 在满足所有功能需求的前提下,只进行我明确要求的修改。
463
+ 即使你认为有更“优化”、“清晰”或“简洁”的表达方式,只要我没有明确要求,也绝不允许进行任何未经指令的修改。
464
+ 目的就是尽可能地保留原有Prompt的字符和结构不变,除非我的功能要求必须改变。
465
+ 例如,如果我只要求你修改一个词,你就不应该修改整句话的结构。
466
+ 严格遵循我的指令:
467
+ 你必须精确地执行我提出的所有具体任务和要求。
468
+ 绝不允许自行添加任何超出指令范围的说明、角色扮演、约束条件或任何非我指令要求的内容。
469
+ 保持原有Prompt的风格和语调:
470
+ 尽可能地与现有Prompt的语言风格、正式程度和语调保持一致。
471
+ 不要改变不相关的句子或其表达方式。
472
+ 只提供修改后的Prompt:
473
+ 直接输出修改后的完整System Prompt文本。
474
+ 不要包含任何解释、说明或额外对话。
475
+ 在你开始之前,请务必确认你已理解并能绝对严格地遵守这些原则。任何未经明确指令的改动都将视为未能完成任务。
476
+
477
+ 现有System Prompt:
478
+ {old_system_prompt}
479
+
480
+ 功能需求:
481
+ {opinion}
482
+ """
483
+
484
+ prompt_ = await self.get_prompts_from_sql(prompt_id = prompt_id,version = version,
485
+ session=session)
486
+ if demand:
487
+ new_prompt = await self.llm.aproduct(
488
+ change_by_opinion_prompt.format(old_system_prompt=prompt_.prompt, opinion=demand)
489
+ )
490
+ else:
491
+ new_prompt = prompt_
492
+ await self.save_prompt_increment_version(prompt_id = prompt_id,
493
+ new_prompt = new_prompt,
494
+ use_case = "",
495
+ score = 60,
496
+ session = session)
497
+
498
+
499
+ async def push_action_order(self,demand : str,prompt_id: str,
500
+ action_type = 'train'):
501
+
502
+ """
503
+ 从sql保存提示词
504
+ 推一个train 状态到指定的位置
505
+
506
+ 将打算修改的状态推上数据库 # 1
507
+ """
508
+ # 查看是否已经存在
509
+ async with create_async_session(self.engine) as session:
510
+
511
+ latest_prompt = await self.get_prompts_from_sql(prompt_id=prompt_id,session=session)
512
+ if latest_prompt:
513
+ await self.save_prompt_increment_version(prompt_id=latest_prompt.prompt_id,
514
+ new_prompt = latest_prompt.prompt,
515
+ use_case = latest_prompt.use_case,
516
+ action_type=action_type,
517
+ demand=demand,
518
+ score=latest_prompt.score,
519
+ session=session
520
+ )
521
+ return "success"
522
+ else:
523
+ await self.save_prompt_increment_version(prompt_id=prompt_id,
524
+ new_prompt = demand,
525
+ use_case = "init",
526
+ action_type="inference",
527
+ demand=demand,
528
+ score=60,
529
+ session=session
530
+ )
531
+ return "init"
532
+
533
+
534
+
535
+ async def intellect_remove(self,
536
+ input_data: dict | str,
537
+ output_format: str,
538
+ prompt_id: str,
539
+ version: str = None,
540
+ inference_save_case = True,
541
+ change_case = False,
542
+ ):
543
+ if isinstance(input_data,dict):
544
+ input_ = json.dumps(input_data,ensure_ascii=False)
545
+ elif isinstance(input_data,str):
546
+ input_ = input_data
547
+
548
+ # 查数据库, 获取最新提示词对象
549
+ async with create_async_session(self.engine) as session:
550
+ result_obj = await self.get_prompts_from_sql(prompt_id=prompt_id,session=session)
551
+ if result_obj is None:
552
+ raise IntellectRemoveError("不存在的prompt_id")
553
+
554
+ prompt = result_obj.prompt
555
+ if result_obj.action_type == "inference":
556
+ # 直接推理即可
557
+ ai_result = await self.llm.aproduct(prompt + output_format + "\nuser:" + input_)
558
+ if inference_save_case:
559
+ await self.save_use_case_by_sql(prompt_id,
560
+ use_case = input_,
561
+ output = ai_result,
562
+ solution = "备注/理想回复",
563
+ session = session,
564
+ )
565
+
566
+ elif result_obj.action_type == "train":
567
+ assert result_obj.demand # 如果type = train 且 demand 是空 则报错
568
+ # 则训练推广
569
+
570
+ # 新版本 默人修改会 inference 状态
571
+ chat_history = prompt
572
+ before_input = result_obj.use_case
573
+ demand = result_obj.demand
574
+
575
+
576
+ # assert demand
577
+ # # 注意, 这里的调整要求使用最初的那个输入, 最好一口气调整好
578
+ # chat_history = prompt
579
+ # if input_ == before_input: # 输入没变, 说明还是针对同一个输入进行讨论
580
+ # # input_prompt = chat_history + "\nuser:" + demand
581
+ # input_prompt = chat_history + "\nuser:" + demand + output_format
582
+ # else:
583
+ # # input_prompt = chat_history + "\nuser:" + demand + "\n-----input----\n" + input_
584
+ # input_prompt = chat_history + "\nuser:" + demand + output_format + "\n-----input----\n" + input_
585
+
586
+ # ai_result = await self.llm.aproduct(input_prompt)
587
+ # chat_history = input_prompt + "\nassistant:\n" + ai_result # 用聊天记录作为完整提示词
588
+ # await self.save_prompt_increment_version(prompt_id, chat_history,
589
+ # use_case = input_,
590
+ # score = 60,
591
+ # session = session)
592
+
593
+
594
+ # version 2
595
+
596
+ # if input_ == before_input:
597
+ # new_prompt = prompt + "\nuser:" + demand
598
+ # else:
599
+ # new_prompt = prompt + "\nuser:" + input_
600
+
601
+ # ai_result = await self.llm.aproduct(new_prompt + output_format)
602
+
603
+ # save_new_prompt = new_prompt + "\nassistant:\n" + ai_result
604
+
605
+
606
+ # await self.save_prompt_increment_version(
607
+ # prompt_id,
608
+ # new_prompt=save_new_prompt,
609
+ # use_case = input_,
610
+ # action_type = "inference",
611
+ # score = 60,
612
+ # session = session)
613
+
614
+ if before_input == "" or change_case is True:
615
+ result_obj.use_case = input_
616
+ await session.commit()
617
+ # 查询上一条, 将before_input 更新位input_
618
+ prompt += input_
619
+
620
+ # 使用更新后的数据进行后续步骤
621
+ new_prompt = prompt + "\nuser:" + demand
622
+
623
+ ai_result = await self.llm.aproduct(new_prompt + output_format)
624
+
625
+ save_new_prompt = new_prompt + "\nassistant:\n" + ai_result
626
+
627
+
628
+ await self.save_prompt_increment_version(
629
+ prompt_id,
630
+ new_prompt=save_new_prompt,
631
+ use_case = input_,
632
+ action_type = "inference",
633
+ score = 60,
634
+ session = session)
635
+
636
+ elif result_obj.action_type == "summary":
637
+
638
+ await self.summary_to_sql(prompt_id = prompt_id,
639
+ prompt = prompt,
640
+ session = session
641
+ )
642
+ ai_result = await self.llm.aproduct(prompt + output_format + "\nuser:" + input_)
643
+
644
+ elif result_obj.action_type == "finetune":
645
+ demand = result_obj.demand
646
+
647
+ assert demand
648
+ await self.prompt_finetune_to_sql(prompt_id = prompt_id,
649
+ demand = demand,
650
+ session = session
651
+ )
652
+ ai_result = await self.llm.aproduct(prompt + output_format + "\nuser:" + input_)
653
+ elif result_obj.action_type == "patch":
654
+ demand = result_obj.demand
655
+ assert demand
656
+ chat_history = prompt + demand
657
+ ai_result = await self.llm.aproduct(chat_history + output_format + "\nuser:" + input_)
658
+ self.save_prompt_increment_version(prompt_id,
659
+ chat_history,
660
+ use_case = input_,
661
+ score = 60,
662
+ session = session)
663
+
664
+ else:
665
+ raise
666
+
667
+ return ai_result
668
+
669
+ async def intellect_stream_remove(self,
670
+ input_data: dict | str,
671
+ output_format: str,
672
+ prompt_id: str,
673
+ version: str = None,
674
+ inference_save_case = True,
675
+ push_patch = False,
676
+ ):
677
+ if isinstance(input_data,dict):
678
+ input_ = json.dumps(input_data,ensure_ascii=False)
679
+ elif isinstance(input_data,str):
680
+ input_ = input_data
681
+
682
+
683
+ # 查数据库, 获取最新提示词对象
684
+ with create_session(self.engine) as session:
685
+ result_obj = await self.get_prompts_from_sql(prompt_id=prompt_id,session=session)
686
+
687
+ '''
688
+ if result_obj is None:
689
+ await self.save_prompt_increment_version(
690
+ prompt_id = prompt_id,
691
+ new_prompt = "做一些处理",
692
+ use_case = input_,
693
+ session = session
694
+ )
695
+ ai_result = await self.intellect_stream_remove(input_data = input_data,
696
+ output_format = output_format,
697
+ prompt_id = prompt_id,
698
+ version = version,
699
+ inference_save_case = inference_save_case
700
+ )
701
+ return ai_result'''
702
+
703
+ prompt = result_obj.prompt
704
+ if result_obj.action_type == "inference":
705
+ # 直接推理即可
706
+
707
+ ai_generate_result = self.llm.aproduct_stream(prompt + output_format + "\n-----input----\n" + input_)
708
+ ai_result = ""
709
+ async for word in ai_generate_result:
710
+ ai_result += word
711
+ yield word
712
+ if inference_save_case:
713
+ await self.save_use_case_by_sql(prompt_id,
714
+ use_case = input_,
715
+ output = ai_result,
716
+ solution = "备注/理想回复",
717
+ session = session,
718
+ )
719
+
720
+ elif result_obj.action_type == "train":
721
+ assert result_obj.demand # 如果type = train 且 demand 是空 则报错
722
+ # 则训练推广
723
+
724
+ # 新版本 默人修改会 inference 状态
725
+ chat_history = prompt
726
+ before_input = result_obj.use_case
727
+ demand = result_obj.demand
728
+
729
+
730
+ assert demand
731
+ # 注意, 这里的调整要求使用最初的那个输入, 最好一口气调整好
732
+ chat_history = prompt
733
+ if input_ == before_input: # 输入没变, 说明还是针对同一个输入进行讨论
734
+ # input_prompt = chat_history + "\nuser:" + demand
735
+ input_prompt = chat_history + "\nuser:" + demand + output_format
736
+ else:
737
+ # input_prompt = chat_history + "\nuser:" + demand + "\n-----input----\n" + input_
738
+ input_prompt = chat_history + "\nuser:" + demand + output_format + "\n-----input----\n" + input_
739
+
740
+ ai_generate_result = self.llm.aproduct_stream(input_prompt)
741
+ ai_result = ""
742
+ async for word in ai_generate_result:
743
+ ai_result += word
744
+ yield word
745
+
746
+ chat_history = input_prompt + "\nassistant:\n" + ai_result # 用聊天记录作为完整提示词
747
+ await self.save_prompt_increment_version(prompt_id, chat_history,
748
+ use_case = input_,
749
+ score = 60,
750
+ session = session)
751
+
752
+
753
+ elif result_obj.action_type == "summary":
754
+
755
+ await self.summary_to_sql(prompt_id = prompt_id,
756
+ prompt = prompt,
757
+ session = session
758
+ )
759
+ input_prompt = prompt + output_format + "\n-----input----\n" + input_
760
+ ai_generate_result = self.llm.aproduct_stream(input_prompt)
761
+ ai_result = ""
762
+ async for word in ai_generate_result:
763
+ ai_result += word
764
+ yield word
765
+
766
+ elif result_obj.action_type == "finetune":
767
+ demand = result_obj.demand
768
+
769
+ assert demand
770
+ await self.prompt_finetune_to_sql(prompt_id = prompt_id,
771
+ demand = demand,
772
+ session = session
773
+ )
774
+ input_prompt = prompt + output_format + "\n-----input----\n" + input_
775
+ ai_generate_result = self.llm.aproduct_stream(input_prompt)
776
+ ai_result = ""
777
+ async for word in ai_generate_result:
778
+ ai_result += word
779
+ yield word
780
+
781
+ elif result_obj.action_type == "patch":
782
+
783
+ demand = result_obj.demand
784
+ assert demand
785
+
786
+ chat_history = prompt + demand
787
+ ai_generate_result = self.llm.aproduct_stream(chat_history + output_format + "\n-----input----\n" + input_)
788
+ ai_result = ""
789
+ async for word in ai_generate_result:
790
+ ai_result += word
791
+ yield word
792
+ if push_patch:
793
+ self.save_prompt_increment_version(prompt_id, chat_history,
794
+ use_case = input_,
795
+ score = 60,
796
+ session = session)
797
+ else:
798
+ raise
799
+
800
+ async def intellect_remove_format(self,
801
+ input_data: dict | str,
802
+ OutputFormat: object,
803
+ prompt_id: str,
804
+ ExtraFormats: list[object] = [],
805
+ version: str = None,
806
+ inference_save_case = True,
807
+ ):
808
+
809
+ base_format_prompt = """
810
+ 按照一定格式输出, 以便可以通过如下校验
811
+
812
+ 使用以下正则检出
813
+ "```json([\s\S]*?)```"
814
+ 使用以下方式验证
815
+ """
816
+ output_format = base_format_prompt + "\n".join([inspect.getsource(outputformat) for outputformat in ExtraFormats]) + inspect.getsource(OutputFormat)
817
+
818
+ ai_result = await self.intellect_remove(
819
+ input_data=input_data,
820
+ output_format=output_format,
821
+ prompt_id=prompt_id,
822
+ version=version,
823
+ inference_save_case=inference_save_case,
824
+ )
825
+
826
+ try:
827
+ json_str = extract_(ai_result,r'json')
828
+ # json_str = fix_broken_json_string(json_str)
829
+ ai_result = json.loads(json_str)
830
+ OutputFormat(**ai_result)
831
+
832
+ except JSONDecodeError as e:
833
+ slog(ai_result,logger=self.logger.error)
834
+ try:
835
+ self.logger.error(f"尝试补救")
836
+ json_str = fix_broken_json_string(json_str)
837
+ ai_result = json.loads(json_str)
838
+ OutputFormat(**ai_result)
839
+
840
+ except JSONDecodeError as e:
841
+ raise IntellectRemoveFormatError(f"prompt_id: {prompt_id} 生成的内容为无法被Json解析 {e}") from e
842
+
843
+ except ValidationError as e:
844
+ err_info = e.errors()[0]
845
+ raise IntellectRemoveFormatError(f"{err_info["type"]}: 属性:{err_info['loc']}, 发生了如下错误: {err_info['msg']}, 格式校验失败, 当前输入为: {err_info['input']} 请检查") from e
846
+
847
+ except Exception as e:
848
+ raise Exception(f"Error {prompt_id} : {e}") from e
849
+
850
+ return ai_result
851
+
852
+ async def intellect_remove_formats(self,
853
+ input_datas: list[dict | str],
854
+ OutputFormat: object,
855
+ prompt_id: str,
856
+ ExtraFormats: list[object] = [],
857
+ version: str = None,
858
+ inference_save_case = True,
859
+ ):
860
+
861
+ async with create_async_session(self.engine) as session:
862
+ prompt_result = await self.get_prompts_from_sql(prompt_id=prompt_id,
863
+ session=session)
864
+ if prompt_result is None:
865
+ raise IntellectRemoveError("不存在的prompt_id")
866
+ if prompt_result.action_type != "inference":
867
+ input_datas = input_datas[:1]
868
+ tasks = []
869
+ for input_data in input_datas:
870
+ tasks.append(
871
+ self.intellect_remove_format(
872
+ input_data = input_data,
873
+ prompt_id = prompt_id,
874
+ OutputFormat = OutputFormat,
875
+ ExtraFormats = ExtraFormats,
876
+ version = version,
877
+ inference_save_case = inference_save_case,
878
+ )
879
+ )
880
+ results = await asyncio.gather(*tasks, return_exceptions=False)
881
+ return results
882
+
883
+ def intellect_remove_warp(self,prompt_id: str):
884
+ def outer_packing(func):
885
+ @functools.wraps(func)
886
+ async def wrapper(*args, **kwargs):
887
+ # 修改逻辑
888
+ assert kwargs.get('input_data') # 要求一定要有data入参
889
+ input_data = kwargs.get('input_data')
890
+ assert kwargs.get('OutputFormat') # 要求一定要有data入参
891
+ OutputFormat = kwargs.get('OutputFormat')
892
+
893
+ if isinstance(input_data,dict):
894
+ input_ = output_ = json.dumps(input_data,ensure_ascii=False)
895
+ elif isinstance(input_data,str):
896
+ input_ = output_ = input_data
897
+
898
+ output_ = await self.intellect_remove_format(
899
+ input_data = input_data,
900
+ prompt_id = prompt_id,
901
+ OutputFormat = OutputFormat,
902
+ )
903
+
904
+ #######
905
+ kwargs.update({"input_data":output_})
906
+ result = await func(*args, **kwargs)
907
+ return result
908
+ return wrapper
909
+ return outer_packing
910
+
911
+ async def intellect_remove_format_eval(self,
912
+ OutputFormat: object,
913
+ prompt_id: str,
914
+ ExtraFormats: list[object] = [],
915
+ version: str = None,
916
+ MIN_SUCCESS_RATE = 80.0
917
+ ):
918
+
919
+ async with create_async_session(self.engine) as session:
920
+ use_cases = await self.get_use_case_by_sql(target_prompt_id=prompt_id,session=session)
921
+ prompt_result = await self.get_prompts_from_sql(prompt_id=prompt_id,
922
+ session=session)
923
+ if prompt_result is None:
924
+ raise IntellectRemoveError("不存在的prompt_id")
925
+ if prompt_result.action_type != "inference":
926
+ raise IntellectRemoveError("请在inference模式下使用次类")
927
+
928
+
929
+ total_assertions = len(use_cases)
930
+ result_cases = []
931
+
932
+ async def evals_func(use_case,prompt_id,OutputFormat,ExtraFormats,version):
933
+ try:
934
+ # 这里将参数传入
935
+ await self.intellect_remove_format(
936
+ input_data = use_case.use_case,
937
+ prompt_id = prompt_id,
938
+ OutputFormat = OutputFormat,
939
+ ExtraFormats = ExtraFormats,
940
+ version = version,
941
+ inference_save_case = False,
942
+ )
943
+ # TODO base_eval
944
+ # TODO 人类评价 eval
945
+ # TODO llm 评价 eval
946
+ result_cases.append({"type":"Successful","case":use_case.use_case,"reply":f"pass"})
947
+ use_case.output = "Successful"
948
+ except IntellectRemoveFormatError as e:
949
+ result_cases.append({"type":"FAILED","case":use_case.use_case,"reply":f"{e}"})
950
+ use_case.output = f"{"FAILED"}-{e}"
951
+ except Exception as e: # 捕获其他可能的错误
952
+ result_cases.append({"type":"FAILED","case":use_case.use_case,"reply":f"Exp {e}"})
953
+ use_case.output = f"{"FAILED"}-{e}"
954
+ await session.commit()
955
+
956
+ tasks = []
957
+ for use_case in use_cases:
958
+ tasks.append(
959
+ evals_func(
960
+ use_case = use_case,
961
+ prompt_id = prompt_id,
962
+ OutputFormat = OutputFormat,
963
+ ExtraFormats = ExtraFormats,
964
+ version = version
965
+ )
966
+ )
967
+ await asyncio.gather(*tasks, return_exceptions=False)
968
+
969
+
970
+ successful_assertions = 0
971
+ bad_case = []
972
+ for i in result_cases:
973
+ if i['type'] == "Successful":
974
+ successful_assertions += 1
975
+ else:
976
+ bad_case.append(i)
977
+
978
+ success_rate = (successful_assertions / total_assertions) * 100
979
+
980
+ if success_rate >= MIN_SUCCESS_RATE:
981
+ return "通过", success_rate, total_assertions, json.dumps(bad_case,ensure_ascii=False),
982
+ else:
983
+ return "未通过",success_rate, total_assertions, json.dumps(bad_case,ensure_ascii=False),
984
+
985
+ # 整体测试d, 测试未通过d, 大模型调整再测试, 依旧不通过, 大模型裂变, 仍不通过, 互换人力
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pro-craft
3
- Version: 0.1.29
3
+ Version: 0.1.30
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.12
6
6
  Description-Content-Type: text/markdown
@@ -13,6 +13,7 @@ src/pro_craft.egg-info/top_level.txt
13
13
  src/pro_craft/code_helper/coder.py
14
14
  src/pro_craft/code_helper/designer.py
15
15
  src/pro_craft/prompt_craft/__init__.py
16
+ src/pro_craft/prompt_craft/async_ copy.py
16
17
  src/pro_craft/prompt_craft/async_.py
17
18
  src/pro_craft/prompt_craft/new.py
18
19
  src/pro_craft/prompt_craft/sync.py
File without changes
File without changes
File without changes