pro-craft 0.1.38__tar.gz → 0.1.39__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.
- {pro_craft-0.1.38 → pro_craft-0.1.39}/PKG-INFO +2 -1
- {pro_craft-0.1.38 → pro_craft-0.1.39}/pyproject.toml +2 -2
- {pro_craft-0.1.38 → pro_craft-0.1.39}/src/pro_craft/database.py +70 -1
- {pro_craft-0.1.38 → pro_craft-0.1.39}/src/pro_craft/prompt_craft/async_.py +37 -23
- pro_craft-0.1.39/src/pro_craft/server/mcp/prompt.py +78 -0
- pro_craft-0.1.39/src/pro_craft/server/router/models.py +35 -0
- pro_craft-0.1.39/src/pro_craft/server/router/prompt.py +163 -0
- {pro_craft-0.1.38 → pro_craft-0.1.39}/src/pro_craft.egg-info/PKG-INFO +2 -1
- {pro_craft-0.1.38 → pro_craft-0.1.39}/src/pro_craft.egg-info/SOURCES.txt +1 -0
- {pro_craft-0.1.38 → pro_craft-0.1.39}/src/pro_craft.egg-info/requires.txt +1 -0
- pro_craft-0.1.38/src/pro_craft/server/mcp/prompt.py +0 -45
- pro_craft-0.1.38/src/pro_craft/server/router/prompt.py +0 -132
- {pro_craft-0.1.38 → pro_craft-0.1.39}/README.md +0 -0
- {pro_craft-0.1.38 → pro_craft-0.1.39}/setup.cfg +0 -0
- {pro_craft-0.1.38 → pro_craft-0.1.39}/src/pro_craft/__init__.py +0 -0
- {pro_craft-0.1.38 → pro_craft-0.1.39}/src/pro_craft/code_helper/coder.py +0 -0
- {pro_craft-0.1.38 → pro_craft-0.1.39}/src/pro_craft/code_helper/designer.py +0 -0
- {pro_craft-0.1.38 → pro_craft-0.1.39}/src/pro_craft/file_manager.py +0 -0
- {pro_craft-0.1.38 → pro_craft-0.1.39}/src/pro_craft/log.py +0 -0
- {pro_craft-0.1.38 → pro_craft-0.1.39}/src/pro_craft/prompt_craft/__init__.py +0 -0
- {pro_craft-0.1.38 → pro_craft-0.1.39}/src/pro_craft/prompt_craft/new.py +0 -0
- {pro_craft-0.1.38 → pro_craft-0.1.39}/src/pro_craft/prompt_craft/sync.py +0 -0
- {pro_craft-0.1.38 → pro_craft-0.1.39}/src/pro_craft/server/mcp/__init__.py +0 -0
- {pro_craft-0.1.38/src/pro_craft/server/router → pro_craft-0.1.39/src/pro_craft/server/mcp}/models.py +0 -0
- {pro_craft-0.1.38 → pro_craft-0.1.39}/src/pro_craft/server/router/__init__.py +0 -0
- {pro_craft-0.1.38 → pro_craft-0.1.39}/src/pro_craft/utils.py +0 -0
- {pro_craft-0.1.38 → pro_craft-0.1.39}/src/pro_craft.egg-info/dependency_links.txt +0 -0
- {pro_craft-0.1.38 → pro_craft-0.1.39}/src/pro_craft.egg-info/top_level.txt +0 -0
- {pro_craft-0.1.38 → pro_craft-0.1.39}/tests/test22.py +0 -0
- {pro_craft-0.1.38 → pro_craft-0.1.39}/tests/test_11.py +0 -0
- {pro_craft-0.1.38 → pro_craft-0.1.39}/tests/test_coder.py +0 -0
- {pro_craft-0.1.38 → pro_craft-0.1.39}/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.
|
|
3
|
+
Version: 0.1.39
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Requires-Python: >=3.12
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -9,6 +9,7 @@ Requires-Dist: anyio>=4.11.0
|
|
|
9
9
|
Requires-Dist: db-help>=0.2.2
|
|
10
10
|
Requires-Dist: fastapi>=0.119.0
|
|
11
11
|
Requires-Dist: llmada>=1.1.11
|
|
12
|
+
Requires-Dist: mcp[cli]>=1.19.0
|
|
12
13
|
Requires-Dist: plotly>=6.3.1
|
|
13
14
|
Requires-Dist: pyyaml>=6.0.3
|
|
14
15
|
Requires-Dist: toml>=0.10.2
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "pro-craft"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.39"
|
|
4
4
|
description = "Add your description here"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
7
|
-
dependencies = [ "aiomysql>=0.2.0", "anyio>=4.11.0", "db-help>=0.2.2", "fastapi>=0.119.0", "llmada>=1.1.11", "plotly>=6.3.1", "pyyaml>=6.0.3", "toml>=0.10.2", "utils-tool==0.1.3", "uvicorn>=0.38.0",]
|
|
7
|
+
dependencies = [ "aiomysql>=0.2.0", "anyio>=4.11.0", "db-help>=0.2.2", "fastapi>=0.119.0", "llmada>=1.1.11", "mcp[cli]>=1.19.0", "plotly>=6.3.1", "pyyaml>=6.0.3", "toml>=0.10.2", "utils-tool==0.1.3", "uvicorn>=0.38.0",]
|
|
8
8
|
|
|
9
9
|
[tool.setuptools.package-data]
|
|
10
10
|
pro_craft = [ "config.yaml",]
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
from sqlalchemy import Column, Integer, String, Text, DateTime, text, UniqueConstraint, Boolean, func
|
|
2
|
+
from sqlalchemy import Column, Integer, String, Text, DateTime, text, UniqueConstraint, Boolean, func, Float
|
|
3
3
|
from sqlalchemy.orm import declarative_base
|
|
4
4
|
|
|
5
5
|
from datetime import datetime, timedelta
|
|
@@ -248,3 +248,72 @@ class UseCase(PromptBase):
|
|
|
248
248
|
f"is_deleted='{self.is_deleted}...'>")
|
|
249
249
|
|
|
250
250
|
|
|
251
|
+
class EvalsInfo(PromptBase):
|
|
252
|
+
__tablename__ = 'ai_evals' # 数据库中的表名,你可以改成你希望的名字
|
|
253
|
+
|
|
254
|
+
# __table_args__ = (
|
|
255
|
+
# UniqueConstraint('prompt_id', 'use_case', name='_prompt_id_version_uc'),
|
|
256
|
+
# # 'name' 参数是可选的,用于给数据库中的约束指定一个名称,方便管理和调试
|
|
257
|
+
# )
|
|
258
|
+
|
|
259
|
+
# id (int, primary_key=True, autoincrement=True)
|
|
260
|
+
# 你的属性表中 id 为 int, true (not null), true (primary key), 0 (length), ASC (key order), true (auto increment)
|
|
261
|
+
id = Column(
|
|
262
|
+
Integer,
|
|
263
|
+
primary_key=True,
|
|
264
|
+
autoincrement=True, # 自动递增
|
|
265
|
+
nullable=False, # 不能为空
|
|
266
|
+
comment="Primary key ID"
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
# prompt_id (varchar 255, not null, unique)
|
|
270
|
+
# 你的属性表中 prompt_id 为 varchar, 255 (length), true (not null)
|
|
271
|
+
prompt_id = Column(
|
|
272
|
+
String(255), # VARCHAR 类型,长度 255
|
|
273
|
+
nullable=False, # 不能为空 # 必须是唯一的,这会创建唯一索引
|
|
274
|
+
comment="Unique identifier for the prompt"
|
|
275
|
+
)
|
|
276
|
+
status = Column(
|
|
277
|
+
String(255), # VARCHAR 类型,长度 255
|
|
278
|
+
nullable=False, # 不能为空 # 必须是唯一的,这会创建唯一索引
|
|
279
|
+
comment="通过/未通过"
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
score = Column(
|
|
283
|
+
Float,
|
|
284
|
+
nullable=False, # 不能为空
|
|
285
|
+
comment="失败次数"
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
total = Column(
|
|
289
|
+
Integer,
|
|
290
|
+
nullable=False, # 不能为空
|
|
291
|
+
comment="失败次数"
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
# prompt (text, not null)
|
|
295
|
+
# 你的属性表中 prompt 为 text, true (not null)
|
|
296
|
+
bad_case = Column(
|
|
297
|
+
Text, # TEXT 类型,适用于长文本
|
|
298
|
+
nullable=False, # 不能为空
|
|
299
|
+
comment="用例"
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
timestamp = Column(
|
|
303
|
+
DateTime,
|
|
304
|
+
nullable=False, # 不能为空
|
|
305
|
+
server_default=text('CURRENT_TIMESTAMP'),
|
|
306
|
+
onupdate=text('CURRENT_TIMESTAMP'),
|
|
307
|
+
comment="时间戳"
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
is_deleted = Column(Boolean, default=False, server_default=text('0'))
|
|
312
|
+
|
|
313
|
+
# 定义 __repr__ 方法以便打印对象时有清晰的表示
|
|
314
|
+
def __repr__(self):
|
|
315
|
+
return (f"<Prompt(id={self.id}, prompt_id='{self.prompt_id}', "
|
|
316
|
+
f"status='{self.status}...', score='{self.score}')>"
|
|
317
|
+
f"total='{self.total}...', score='{self.score}')>"
|
|
318
|
+
f"is_deleted='{self.is_deleted}...'>")
|
|
319
|
+
|
|
@@ -421,6 +421,10 @@ class AsyncIntel():
|
|
|
421
421
|
inference_save_case = True,
|
|
422
422
|
change_case = False,
|
|
423
423
|
):
|
|
424
|
+
"""
|
|
425
|
+
自定自动化执行命令的方法,
|
|
426
|
+
不涉及严格的校验, 主要职能在自动化的修改提示词, 或者管理提示词上
|
|
427
|
+
"""
|
|
424
428
|
if isinstance(input_data,dict):
|
|
425
429
|
input_ = json.dumps(input_data,ensure_ascii=False)
|
|
426
430
|
elif isinstance(input_data,str):
|
|
@@ -634,7 +638,16 @@ class AsyncIntel():
|
|
|
634
638
|
ExtraFormats: list[object] = [],
|
|
635
639
|
version: str = None,
|
|
636
640
|
inference_save_case = True,
|
|
641
|
+
ConTent_Function = None,
|
|
642
|
+
AConTent_Function = None,
|
|
637
643
|
):
|
|
644
|
+
"""
|
|
645
|
+
这个format 是严格校验模式, 是interllect 的增强版, 会主动校验内容,并及时抛出异常(或者伺机修正)
|
|
646
|
+
ConTent_Function
|
|
647
|
+
AConTent_Function
|
|
648
|
+
两种方式的传入方式, 内容未通过就抛出异常
|
|
649
|
+
|
|
650
|
+
"""
|
|
638
651
|
|
|
639
652
|
base_format_prompt = """
|
|
640
653
|
按照一定格式输出, 以便可以通过如下校验
|
|
@@ -676,6 +689,12 @@ class AsyncIntel():
|
|
|
676
689
|
|
|
677
690
|
except Exception as e:
|
|
678
691
|
raise Exception(f"Error {prompt_id} : {e}") from e
|
|
692
|
+
|
|
693
|
+
if ConTent_Function:
|
|
694
|
+
ConTent_Function(ai_result)
|
|
695
|
+
|
|
696
|
+
if AConTent_Function:
|
|
697
|
+
await AConTent_Function(ai_result)
|
|
679
698
|
|
|
680
699
|
return ai_result
|
|
681
700
|
|
|
@@ -686,6 +705,7 @@ class AsyncIntel():
|
|
|
686
705
|
ExtraFormats: list[object] = [],
|
|
687
706
|
version: str = None,
|
|
688
707
|
inference_save_case = True,
|
|
708
|
+
**kwargs,
|
|
689
709
|
):
|
|
690
710
|
|
|
691
711
|
async with create_async_session(self.engine) as session:
|
|
@@ -705,6 +725,7 @@ class AsyncIntel():
|
|
|
705
725
|
ExtraFormats = ExtraFormats,
|
|
706
726
|
version = version,
|
|
707
727
|
inference_save_case = inference_save_case,
|
|
728
|
+
**kwargs,
|
|
708
729
|
)
|
|
709
730
|
)
|
|
710
731
|
results = await asyncio.gather(*tasks, return_exceptions=False)
|
|
@@ -717,8 +738,7 @@ class AsyncIntel():
|
|
|
717
738
|
# 修改逻辑
|
|
718
739
|
assert kwargs.get('input_data') # 要求一定要有data入参
|
|
719
740
|
input_data = kwargs.get('input_data')
|
|
720
|
-
|
|
721
|
-
|
|
741
|
+
kwargs.pop(input_data)
|
|
722
742
|
if isinstance(input_data,dict):
|
|
723
743
|
input_ = output_ = json.dumps(input_data,ensure_ascii=False)
|
|
724
744
|
elif isinstance(input_data,str):
|
|
@@ -727,7 +747,8 @@ class AsyncIntel():
|
|
|
727
747
|
output_ = await self.intellect_format(
|
|
728
748
|
input_data = input_data,
|
|
729
749
|
prompt_id = prompt_id,
|
|
730
|
-
|
|
750
|
+
**kwargs,
|
|
751
|
+
|
|
731
752
|
)
|
|
732
753
|
|
|
733
754
|
#######
|
|
@@ -787,12 +808,9 @@ class AsyncIntel():
|
|
|
787
808
|
ExtraFormats = ExtraFormats,
|
|
788
809
|
version = version,
|
|
789
810
|
inference_save_case = False,
|
|
811
|
+
ConTent_Function = ConTent_Function,
|
|
812
|
+
AConTent_Function = AConTent_Function,
|
|
790
813
|
)
|
|
791
|
-
if ConTent_Function:
|
|
792
|
-
ConTent_Function(ai_result)
|
|
793
|
-
|
|
794
|
-
if AConTent_Function:
|
|
795
|
-
await AConTent_Function(ai_result)
|
|
796
814
|
|
|
797
815
|
result_cases.append({"type":"Successful","case":use_case.use_case,"reply":f"pass"})
|
|
798
816
|
use_case.output = json.dumps(ai_result,ensure_ascii=False,indent=4)
|
|
@@ -835,13 +853,22 @@ class AsyncIntel():
|
|
|
835
853
|
|
|
836
854
|
success_rate = (successful_assertions / total_assertions) * 100
|
|
837
855
|
|
|
856
|
+
|
|
838
857
|
if success_rate >= MIN_SUCCESS_RATE:
|
|
858
|
+
self.eval_df.loc[len(self.eval_df)] = {"name":prompt_id,
|
|
859
|
+
'status':"通过",
|
|
860
|
+
"score":success_rate,
|
|
861
|
+
"total":str(total_assertions),
|
|
862
|
+
"bad_case":json.dumps(bad_case,ensure_ascii=False)}
|
|
839
863
|
return "通过", success_rate, str(total_assertions), json.dumps(bad_case,ensure_ascii=False),
|
|
840
864
|
else:
|
|
865
|
+
self.eval_df.loc[len(self.eval_df)] = {"name":prompt_id,
|
|
866
|
+
'status':"未通过",
|
|
867
|
+
"score":success_rate,
|
|
868
|
+
"total":str(total_assertions),
|
|
869
|
+
"bad_case":json.dumps(bad_case,ensure_ascii=False)}
|
|
841
870
|
return "未通过",success_rate, str(total_assertions), json.dumps(bad_case,ensure_ascii=False),
|
|
842
871
|
|
|
843
|
-
|
|
844
|
-
|
|
845
872
|
def draw_data(self,save_html_path):
|
|
846
873
|
df = self.eval_df
|
|
847
874
|
# --- 可视化部分 ---
|
|
@@ -926,18 +953,5 @@ class AsyncIntel():
|
|
|
926
953
|
if save_html_path:
|
|
927
954
|
fig.write_html(save_html_path)
|
|
928
955
|
|
|
929
|
-
async def _evals(self,prompt_id, OutputFormat, ExtraFormats_list = [],database_url = None,**kwargs):
|
|
930
|
-
|
|
931
|
-
status,score, total, bad_case = await self.intellect_format_eval(
|
|
932
|
-
prompt_id=prompt_id,
|
|
933
|
-
OutputFormat = OutputFormat,
|
|
934
|
-
ExtraFormats = ExtraFormats_list,
|
|
935
|
-
version = None,
|
|
936
|
-
database_url = database_url,
|
|
937
|
-
**kwargs
|
|
938
|
-
)
|
|
939
|
-
self.eval_df.loc[len(self.eval_df)] = {"name":prompt_id,
|
|
940
|
-
'status':status,"score":score,
|
|
941
|
-
"total":total,"bad_case":bad_case}
|
|
942
956
|
|
|
943
957
|
# 整体测试d, 测试未通过d, 大模型调整再测试, 依旧不通过, 大模型裂变, 仍不通过, 互换人力
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
from mcp.server.fastmcp import FastMCP
|
|
2
|
+
|
|
3
|
+
from pro_craft import Intel,AsyncIntel
|
|
4
|
+
from .models import *
|
|
5
|
+
|
|
6
|
+
def create_mcp(database_url: str,
|
|
7
|
+
slave_database_url: str,
|
|
8
|
+
model_name: str,
|
|
9
|
+
logger = None):
|
|
10
|
+
# region MCP Weather
|
|
11
|
+
mcp = FastMCP("Prompt")
|
|
12
|
+
|
|
13
|
+
intels = AsyncIntel(
|
|
14
|
+
database_url=database_url,
|
|
15
|
+
model_name=model_name,
|
|
16
|
+
logger=logger
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
@mcp.tool()
|
|
20
|
+
async def push_order(demand: str, prompt_id: str, action_type: str):
|
|
21
|
+
"""
|
|
22
|
+
希望大模型进行哪种模式的调整
|
|
23
|
+
demand: str = Field(None, description="信息")
|
|
24
|
+
prompt_id: str = Field(..., description="提示词id")
|
|
25
|
+
action_type: str = Field(..., description="执行动作",min_length=1, max_length=10)
|
|
26
|
+
"""
|
|
27
|
+
try:
|
|
28
|
+
PushOrderRequest(demand=demand,prompt_id=prompt_id,action_type=action_type)
|
|
29
|
+
result = await intels.push_action_order(
|
|
30
|
+
demand=demand,
|
|
31
|
+
prompt_id=prompt_id,
|
|
32
|
+
action_type=action_type
|
|
33
|
+
)
|
|
34
|
+
return PromptResponse(msg = "success",content=result)
|
|
35
|
+
except Exception as e:
|
|
36
|
+
return f"Error : {e}"
|
|
37
|
+
|
|
38
|
+
@mcp.tool()
|
|
39
|
+
async def get_registered_prompt():
|
|
40
|
+
"获取以注册的可修改的提示词id"
|
|
41
|
+
try:
|
|
42
|
+
result = ["memorycard-format",
|
|
43
|
+
"memorycard-polish",
|
|
44
|
+
"memorycard-merge",
|
|
45
|
+
"memorycard-score",
|
|
46
|
+
"memorycard-generate-content",
|
|
47
|
+
"user-overview",
|
|
48
|
+
"user-relationship-extraction",
|
|
49
|
+
"avatar-brief",
|
|
50
|
+
"avatar-personality-extraction",
|
|
51
|
+
"avatar-desensitization",
|
|
52
|
+
"biograph-free-writer",
|
|
53
|
+
"biograph-paid-title",
|
|
54
|
+
"biograph-outline",
|
|
55
|
+
"biograph-brief",
|
|
56
|
+
"biograph-extract-person-name",
|
|
57
|
+
"biograph-extract-place",
|
|
58
|
+
"biograph-extract-material",
|
|
59
|
+
"biograph-writer"]
|
|
60
|
+
|
|
61
|
+
return PromptResponse(msg = "success",content=result)
|
|
62
|
+
except Exception as e:
|
|
63
|
+
return f"Error : {e}"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@mcp.tool()
|
|
67
|
+
async def sync_database():
|
|
68
|
+
try:
|
|
69
|
+
result = await intels.sync_production_database(slave_database_url)
|
|
70
|
+
return PromptResponse(msg = "success",content=result)
|
|
71
|
+
except Exception as e:
|
|
72
|
+
return f"Error : {e}"
|
|
73
|
+
|
|
74
|
+
return mcp
|
|
75
|
+
|
|
76
|
+
if __name__ == "__main__":
|
|
77
|
+
mcp = create_mcp()
|
|
78
|
+
mcp.run(transport="streamable-http")
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from typing import Dict, Any, Optional, List
|
|
2
|
+
from pydantic import BaseModel, Field, model_validator, field_validator, RootModel
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
class PushOrderRequest(BaseModel):
|
|
6
|
+
demand: str = Field(None, description="信息")
|
|
7
|
+
prompt_id: str = Field(..., description="提示词id")
|
|
8
|
+
action_type: str = Field(..., description="执行动作",min_length=1, max_length=10)
|
|
9
|
+
|
|
10
|
+
@field_validator('action_type')
|
|
11
|
+
@classmethod
|
|
12
|
+
def validate_action_type(cls, v: str) -> str:
|
|
13
|
+
if v in ['train','inference','summary','finetune','patch']:
|
|
14
|
+
return v
|
|
15
|
+
else:
|
|
16
|
+
raise ValueError(f"无效action_type: {v}")
|
|
17
|
+
|
|
18
|
+
class GetPromptRequest(BaseModel):
|
|
19
|
+
prompt_id: str = Field(..., description="提示词id")
|
|
20
|
+
|
|
21
|
+
class UpdatePromptRequest(BaseModel):
|
|
22
|
+
prompt_id: str = Field(..., description="提示词id")
|
|
23
|
+
prompt: str = Field(..., description="新的提示词")
|
|
24
|
+
|
|
25
|
+
class RollBackPromptRequest(BaseModel):
|
|
26
|
+
prompt_id: str = Field(..., description="提示词id")
|
|
27
|
+
version: str = Field(..., description="版本号")
|
|
28
|
+
|
|
29
|
+
class SyncDataBaseRequest(BaseModel):
|
|
30
|
+
slave_database_url: str = Field(None, description="从属数据库url")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class PromptResponse(BaseModel):
|
|
34
|
+
msg: str = Field(..., description="信息")
|
|
35
|
+
content: str = None
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
from fastapi import APIRouter
|
|
4
|
+
from pro_craft import Intel,AsyncIntel
|
|
5
|
+
from pro_craft.utils import create_async_session
|
|
6
|
+
from fastapi import FastAPI, HTTPException
|
|
7
|
+
from .models import *
|
|
8
|
+
|
|
9
|
+
def create_router(database_url: str,
|
|
10
|
+
slave_database_url: str,
|
|
11
|
+
model_name: str,
|
|
12
|
+
logger = None):
|
|
13
|
+
"""
|
|
14
|
+
# TODO 整理改为异步
|
|
15
|
+
创建一个包含 ProCraft 路由的 FastAPI APIRouter 实例。
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
database_url (str): 数据库连接字符串。
|
|
19
|
+
model_name (str): 用于 Intel 实例的模型名称。
|
|
20
|
+
api_key_secret (str, optional): 用于验证 API Key 的秘密字符串。
|
|
21
|
+
如果提供,它将覆盖环境变量 PRO_CRAFT_API_KEY。
|
|
22
|
+
如果都不提供,会使用硬编码的 'your_default_secret_key'。
|
|
23
|
+
Returns:
|
|
24
|
+
APIRouter: 配置好的 FastAPI APIRouter 实例。
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
intels = AsyncIntel(
|
|
28
|
+
database_url=database_url,
|
|
29
|
+
model_name=model_name,
|
|
30
|
+
logger=logger
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
router = APIRouter(
|
|
34
|
+
tags=["prompt"] # 这里使用 Depends 确保每次请求都验证
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# 自动修改
|
|
38
|
+
@router.post("/push_order",
|
|
39
|
+
description="可选 train,inference,summary,finetune,patch",
|
|
40
|
+
response_model=PromptResponse,
|
|
41
|
+
)
|
|
42
|
+
async def push_order(request: PushOrderRequest):
|
|
43
|
+
try:
|
|
44
|
+
result = await intels.push_action_order(
|
|
45
|
+
demand=request.demand,
|
|
46
|
+
prompt_id=request.prompt_id,
|
|
47
|
+
action_type=request.action_type
|
|
48
|
+
)
|
|
49
|
+
return PromptResponse(msg = "success",content=result)
|
|
50
|
+
except Exception as e:
|
|
51
|
+
raise HTTPException(
|
|
52
|
+
status_code=500, detail=f"{e}"
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# 人为干预
|
|
56
|
+
|
|
57
|
+
@router.get("/registered_prompt",
|
|
58
|
+
description="获取以注册的提示词",
|
|
59
|
+
response_model=PromptResponse)
|
|
60
|
+
async def get_prompt():
|
|
61
|
+
try:
|
|
62
|
+
result = ["memorycard-format",
|
|
63
|
+
"memorycard-polish",
|
|
64
|
+
"memorycard-merge",
|
|
65
|
+
"memorycard-score",
|
|
66
|
+
"memorycard-generate-content",
|
|
67
|
+
"user-overview",
|
|
68
|
+
"user-relationship-extraction",
|
|
69
|
+
"avatar-brief",
|
|
70
|
+
"avatar-personality-extraction",
|
|
71
|
+
"avatar-desensitization",
|
|
72
|
+
"biograph-free-writer",
|
|
73
|
+
"biograph-paid-title",
|
|
74
|
+
"biograph-outline",
|
|
75
|
+
"biograph-brief",
|
|
76
|
+
"biograph-extract-person-name",
|
|
77
|
+
"biograph-extract-place",
|
|
78
|
+
"biograph-extract-material",
|
|
79
|
+
"biograph-writer"]
|
|
80
|
+
|
|
81
|
+
return PromptResponse(msg = "success",content=result)
|
|
82
|
+
except Exception as e:
|
|
83
|
+
raise HTTPException(
|
|
84
|
+
status_code=500, detail=f"{e}"
|
|
85
|
+
)
|
|
86
|
+
@router.post("/get_prompt",
|
|
87
|
+
description="获得现行提示词",
|
|
88
|
+
response_model=PromptResponse)
|
|
89
|
+
async def get_prompt(request: GetPromptRequest):
|
|
90
|
+
try:
|
|
91
|
+
async with create_async_session(intels.engine) as session:
|
|
92
|
+
result = await intels.get_prompt_safe(
|
|
93
|
+
prompt_id=request.prompt_id,
|
|
94
|
+
session=session
|
|
95
|
+
)
|
|
96
|
+
return PromptResponse(msg = "success",content=result)
|
|
97
|
+
|
|
98
|
+
except Exception as e:
|
|
99
|
+
raise HTTPException(
|
|
100
|
+
status_code=500, detail=f"{e}"
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
@router.post("/update_prompt",
|
|
104
|
+
description="更新现行提示词",
|
|
105
|
+
response_model=PromptResponse)
|
|
106
|
+
async def update_prompt(request: UpdatePromptRequest):
|
|
107
|
+
try:
|
|
108
|
+
async with create_async_session(intels.engine) as session:
|
|
109
|
+
await intels.save_prompt(
|
|
110
|
+
prompt_id = request.prompt_id,
|
|
111
|
+
new_prompt = request.prompt,
|
|
112
|
+
use_case = "",
|
|
113
|
+
action_type = "inference",
|
|
114
|
+
demand = "上传",
|
|
115
|
+
score = 70,
|
|
116
|
+
session = session)
|
|
117
|
+
return PromptResponse(msg = "success",content=None)
|
|
118
|
+
except Exception as e:
|
|
119
|
+
raise HTTPException(
|
|
120
|
+
status_code=500, detail=f"{e}"
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
@router.post("/rollback_prompt",
|
|
124
|
+
description="回滚现行提示词",
|
|
125
|
+
response_model=PromptResponse)
|
|
126
|
+
async def roll_back(request: RollBackPromptRequest):
|
|
127
|
+
try:
|
|
128
|
+
async with create_async_session(intels.engine) as session:
|
|
129
|
+
result = await intels.get_prompt_safe(
|
|
130
|
+
prompt_id=request.prompt_id,
|
|
131
|
+
version = request.version,
|
|
132
|
+
session=session
|
|
133
|
+
)
|
|
134
|
+
assert result.version == request.version
|
|
135
|
+
await intels.save_prompt(
|
|
136
|
+
prompt_id = request.prompt_id,
|
|
137
|
+
new_prompt = result.prompt,
|
|
138
|
+
use_case = result.use_case,
|
|
139
|
+
action_type = "inference",
|
|
140
|
+
demand = "",
|
|
141
|
+
score = 61,
|
|
142
|
+
session = session)
|
|
143
|
+
return PromptResponse(msg = "success",content=None)
|
|
144
|
+
except Exception as e:
|
|
145
|
+
raise HTTPException(
|
|
146
|
+
status_code=500, detail=f"{e}"
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
#系统级别服务
|
|
151
|
+
|
|
152
|
+
@router.post("/sync_database")
|
|
153
|
+
async def sync_database(request: SyncDataBaseRequest):
|
|
154
|
+
try:
|
|
155
|
+
slave_database_url = request.slave_database_url or slave_database_url
|
|
156
|
+
result = await intels.sync_production_database(slave_database_url)
|
|
157
|
+
return PromptResponse(msg = "success",content=result)
|
|
158
|
+
except Exception as e:
|
|
159
|
+
raise HTTPException(
|
|
160
|
+
status_code=500, detail=f"{e}"
|
|
161
|
+
)
|
|
162
|
+
return router
|
|
163
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pro-craft
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.39
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Requires-Python: >=3.12
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -9,6 +9,7 @@ Requires-Dist: anyio>=4.11.0
|
|
|
9
9
|
Requires-Dist: db-help>=0.2.2
|
|
10
10
|
Requires-Dist: fastapi>=0.119.0
|
|
11
11
|
Requires-Dist: llmada>=1.1.11
|
|
12
|
+
Requires-Dist: mcp[cli]>=1.19.0
|
|
12
13
|
Requires-Dist: plotly>=6.3.1
|
|
13
14
|
Requires-Dist: pyyaml>=6.0.3
|
|
14
15
|
Requires-Dist: toml>=0.10.2
|
|
@@ -17,6 +17,7 @@ src/pro_craft/prompt_craft/async_.py
|
|
|
17
17
|
src/pro_craft/prompt_craft/new.py
|
|
18
18
|
src/pro_craft/prompt_craft/sync.py
|
|
19
19
|
src/pro_craft/server/mcp/__init__.py
|
|
20
|
+
src/pro_craft/server/mcp/models.py
|
|
20
21
|
src/pro_craft/server/mcp/prompt.py
|
|
21
22
|
src/pro_craft/server/router/__init__.py
|
|
22
23
|
src/pro_craft/server/router/models.py
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
from mcp.server.fastmcp import FastMCP
|
|
2
|
-
|
|
3
|
-
from pro_craft import Intel
|
|
4
|
-
|
|
5
|
-
def create_mcp(database_url: str,
|
|
6
|
-
slave_database_url: str,
|
|
7
|
-
model_name: str):
|
|
8
|
-
# region MCP Weather
|
|
9
|
-
mcp = FastMCP("PromptManager")
|
|
10
|
-
|
|
11
|
-
intels = Intel(
|
|
12
|
-
database_url=database_url,
|
|
13
|
-
model_name=model_name
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
@mcp.tool()
|
|
17
|
-
def push_order(demand: str, prompt_id: str, action_type: str = "train") -> str:
|
|
18
|
-
result = intels.push_action_order(
|
|
19
|
-
demand=demand,
|
|
20
|
-
prompt_id=prompt_id,
|
|
21
|
-
action_type=action_type
|
|
22
|
-
)
|
|
23
|
-
return {"message": "success", "result": result}
|
|
24
|
-
|
|
25
|
-
@mcp.tool()
|
|
26
|
-
def get_latest_prompt(prompt_id: str) -> str:
|
|
27
|
-
with create_session(intels.engine) as session:
|
|
28
|
-
result = intels.get_prompts_from_sql(
|
|
29
|
-
prompt_id=prompt_id,
|
|
30
|
-
session=session
|
|
31
|
-
)
|
|
32
|
-
return {"message": "success", "result": result}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
@mcp.tool()
|
|
36
|
-
def sync_database() -> str:
|
|
37
|
-
result = intels.sync_prompt_data_to_database(slave_database_url)
|
|
38
|
-
return {"message": "success","result":result}
|
|
39
|
-
|
|
40
|
-
return mcp
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if __name__ == "__main__":
|
|
44
|
-
mcp = create_mcp()
|
|
45
|
-
mcp.run(transport="streamable-http")
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
from fastapi import APIRouter
|
|
4
|
-
from pro_craft import Intel,AsyncIntel
|
|
5
|
-
from pro_craft.utils import create_async_session
|
|
6
|
-
from .models import *
|
|
7
|
-
|
|
8
|
-
def create_router(database_url: str,
|
|
9
|
-
slave_database_url: str,
|
|
10
|
-
model_name: str,
|
|
11
|
-
logger = None):
|
|
12
|
-
"""
|
|
13
|
-
# TODO 整理改为异步
|
|
14
|
-
创建一个包含 ProCraft 路由的 FastAPI APIRouter 实例。
|
|
15
|
-
|
|
16
|
-
Args:
|
|
17
|
-
database_url (str): 数据库连接字符串。
|
|
18
|
-
model_name (str): 用于 Intel 实例的模型名称。
|
|
19
|
-
api_key_secret (str, optional): 用于验证 API Key 的秘密字符串。
|
|
20
|
-
如果提供,它将覆盖环境变量 PRO_CRAFT_API_KEY。
|
|
21
|
-
如果都不提供,会使用硬编码的 'your_default_secret_key'。
|
|
22
|
-
Returns:
|
|
23
|
-
APIRouter: 配置好的 FastAPI APIRouter 实例。
|
|
24
|
-
"""
|
|
25
|
-
|
|
26
|
-
intels = AsyncIntel(
|
|
27
|
-
database_url=database_url,
|
|
28
|
-
model_name=model_name,
|
|
29
|
-
logger=logger
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
router = APIRouter(
|
|
33
|
-
tags=["prompt"] # 这里使用 Depends 确保每次请求都验证
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
# 自动修改
|
|
37
|
-
@router.post("/push_order",
|
|
38
|
-
description="可选 train,inference,summary,finetune,patch",
|
|
39
|
-
response_model=PromptResponse,
|
|
40
|
-
)
|
|
41
|
-
async def push_order(request: PushOrderRequest):
|
|
42
|
-
result = await intels.push_action_order(
|
|
43
|
-
demand=request.demand,
|
|
44
|
-
prompt_id=request.prompt_id,
|
|
45
|
-
action_type=request.action_type
|
|
46
|
-
)
|
|
47
|
-
return PromptResponse(msg = "success",content=result)
|
|
48
|
-
|
|
49
|
-
# 人为干预
|
|
50
|
-
|
|
51
|
-
@router.get("/registered_prompt",
|
|
52
|
-
description="获取以注册的提示词",
|
|
53
|
-
response_model=PromptResponse)
|
|
54
|
-
async def get_prompt():
|
|
55
|
-
result = ["memorycard-format",
|
|
56
|
-
"memorycard-polish",
|
|
57
|
-
"memorycard-merge",
|
|
58
|
-
"memorycard-score",
|
|
59
|
-
"memorycard-generate-content",
|
|
60
|
-
"user-overview",
|
|
61
|
-
"user-relationship-extraction",
|
|
62
|
-
"avatar-brief",
|
|
63
|
-
"avatar-personality-extraction",
|
|
64
|
-
"avatar-desensitization",
|
|
65
|
-
"biograph-free-writer",
|
|
66
|
-
"biograph-paid-title",
|
|
67
|
-
"biograph-outline",
|
|
68
|
-
"biograph-brief",
|
|
69
|
-
"biograph-extract-person-name",
|
|
70
|
-
"biograph-extract-place",
|
|
71
|
-
"biograph-extract-material",
|
|
72
|
-
"biograph-writer"]
|
|
73
|
-
|
|
74
|
-
return PromptResponse(msg = "success",content=result)
|
|
75
|
-
|
|
76
|
-
@router.post("/get_prompt",
|
|
77
|
-
description="获得现行提示词",
|
|
78
|
-
response_model=PromptResponse)
|
|
79
|
-
async def get_prompt(request: GetPromptRequest):
|
|
80
|
-
async with create_async_session(intels.engine) as session:
|
|
81
|
-
result = await intels.get_prompt_safe(
|
|
82
|
-
prompt_id=request.prompt_id,
|
|
83
|
-
session=session
|
|
84
|
-
)
|
|
85
|
-
return PromptResponse(msg = "success",content=result)
|
|
86
|
-
|
|
87
|
-
@router.post("/update_prompt",
|
|
88
|
-
description="更新现行提示词",
|
|
89
|
-
response_model=PromptResponse)
|
|
90
|
-
async def update_prompt(request: UpdatePromptRequest):
|
|
91
|
-
async with create_async_session(intels.engine) as session:
|
|
92
|
-
await intels.save_prompt(
|
|
93
|
-
prompt_id = request.prompt_id,
|
|
94
|
-
new_prompt = request.prompt,
|
|
95
|
-
use_case = "",
|
|
96
|
-
action_type = "inference",
|
|
97
|
-
demand = "上传",
|
|
98
|
-
score = 70,
|
|
99
|
-
session = session)
|
|
100
|
-
return PromptResponse(msg = "success",content=None)
|
|
101
|
-
|
|
102
|
-
@router.post("/rollback_prompt",
|
|
103
|
-
description="回滚现行提示词",
|
|
104
|
-
response_model=PromptResponse)
|
|
105
|
-
async def roll_back(request: RollBackPromptRequest):
|
|
106
|
-
async with create_async_session(intels.engine) as session:
|
|
107
|
-
result = await intels.get_prompt_safe(
|
|
108
|
-
prompt_id=request.prompt_id,
|
|
109
|
-
version = request.version,
|
|
110
|
-
session=session
|
|
111
|
-
)
|
|
112
|
-
assert result.version == request.version
|
|
113
|
-
await intels.save_prompt(
|
|
114
|
-
prompt_id = request.prompt_id,
|
|
115
|
-
new_prompt = result.prompt,
|
|
116
|
-
use_case = result.use_case,
|
|
117
|
-
action_type = "inference",
|
|
118
|
-
demand = "",
|
|
119
|
-
score = 61,
|
|
120
|
-
session = session)
|
|
121
|
-
return PromptResponse(msg = "success",content=None)
|
|
122
|
-
|
|
123
|
-
#系统级别服务
|
|
124
|
-
|
|
125
|
-
@router.post("/sync_database")
|
|
126
|
-
async def sync_database(request: SyncDataBaseRequest):
|
|
127
|
-
slave_database_url = request.slave_database_url or slave_database_url
|
|
128
|
-
result = await intels.sync_production_database(slave_database_url)
|
|
129
|
-
return PromptResponse(msg = "success",content=result)
|
|
130
|
-
|
|
131
|
-
return router
|
|
132
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pro_craft-0.1.38/src/pro_craft/server/router → pro_craft-0.1.39/src/pro_craft/server/mcp}/models.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|