pro-craft 0.1.16__tar.gz → 0.2.66__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.
- {pro_craft-0.1.16 → pro_craft-0.2.66}/PKG-INFO +10 -6
- {pro_craft-0.1.16 → pro_craft-0.2.66}/README.md +4 -0
- {pro_craft-0.1.16 → pro_craft-0.2.66}/pyproject.toml +2 -2
- pro_craft-0.2.66/src/pro_craft/__init__.py +10 -0
- pro_craft-0.2.66/src/pro_craft/code_helper/agent.py +87 -0
- pro_craft-0.2.66/src/pro_craft/code_helper/codermanager.py +143 -0
- pro_craft-0.2.66/src/pro_craft/code_helper/new_code/paper_program.py +183 -0
- pro_craft-0.2.66/src/pro_craft/code_helper/tools.py +182 -0
- pro_craft-0.2.66/src/pro_craft/code_helper/utils/database.py +36 -0
- pro_craft-0.2.66/src/pro_craft/code_helper/utils/template_extract.py +134 -0
- pro_craft-0.2.66/src/pro_craft/code_helper/utils/vectorstore.py +81 -0
- {pro_craft-0.1.16 → pro_craft-0.2.66}/src/pro_craft/database.py +47 -30
- {pro_craft-0.1.16 → pro_craft-0.2.66}/src/pro_craft/file_manager.py +2 -2
- pro_craft-0.2.66/src/pro_craft/log.py +112 -0
- pro_craft-0.2.66/src/pro_craft/prompt_craft/__init__.py +2 -0
- pro_craft-0.2.66/src/pro_craft/prompt_craft/async_.py +947 -0
- {pro_craft-0.1.16 → pro_craft-0.2.66}/src/pro_craft/prompt_craft/sync.py +53 -41
- pro_craft-0.2.66/src/pro_craft/server/mcp/models.py +35 -0
- pro_craft-0.2.66/src/pro_craft/server/mcp/prompt.py +78 -0
- pro_craft-0.2.66/src/pro_craft/server/router/__init__.py +0 -0
- pro_craft-0.2.66/src/pro_craft/server/router/coder_template.py +54 -0
- pro_craft-0.2.66/src/pro_craft/server/router/models.py +40 -0
- pro_craft-0.2.66/src/pro_craft/server/router/prompt.py +240 -0
- {pro_craft-0.1.16 → pro_craft-0.2.66}/src/pro_craft.egg-info/PKG-INFO +10 -6
- {pro_craft-0.1.16 → pro_craft-0.2.66}/src/pro_craft.egg-info/SOURCES.txt +15 -6
- {pro_craft-0.1.16 → pro_craft-0.2.66}/src/pro_craft.egg-info/requires.txt +5 -5
- pro_craft-0.2.66/tests/test_11.py +42 -0
- {pro_craft-0.1.16 → pro_craft-0.2.66}/tests/test_coder.py +2 -2
- pro_craft-0.2.66/tests/test_core.py +24 -0
- pro_craft-0.2.66/tests/test_intel.py +188 -0
- pro_craft-0.2.66/tests/test_store.py +48 -0
- pro_craft-0.1.16/src/pro_craft/__init__.py +0 -23
- pro_craft-0.1.16/src/pro_craft/code_helper/coder.py +0 -660
- pro_craft-0.1.16/src/pro_craft/code_helper/designer.py +0 -115
- pro_craft-0.1.16/src/pro_craft/log.py +0 -82
- pro_craft-0.1.16/src/pro_craft/prompt_craft/__init__.py +0 -3
- pro_craft-0.1.16/src/pro_craft/prompt_craft/async_.py +0 -633
- pro_craft-0.1.16/src/pro_craft/prompt_craft/evals.py +0 -61
- pro_craft-0.1.16/src/pro_craft/prompt_craft/new.py +0 -605
- pro_craft-0.1.16/src/pro_craft/server/mcp/prompt.py +0 -45
- pro_craft-0.1.16/src/pro_craft/server/router/prompt.py +0 -55
- pro_craft-0.1.16/tests/test22.py +0 -146
- pro_craft-0.1.16/tests/test_designer.py +0 -30
- {pro_craft-0.1.16 → pro_craft-0.2.66}/setup.cfg +0 -0
- {pro_craft-0.1.16/src/pro_craft/server/router → pro_craft-0.2.66/src/pro_craft/code_helper}/__init__.py +0 -0
- {pro_craft-0.1.16 → pro_craft-0.2.66}/src/pro_craft/server/mcp/__init__.py +0 -0
- {pro_craft-0.1.16 → pro_craft-0.2.66}/src/pro_craft/utils.py +0 -0
- {pro_craft-0.1.16 → pro_craft-0.2.66}/src/pro_craft.egg-info/dependency_links.txt +0 -0
- {pro_craft-0.1.16 → pro_craft-0.2.66}/src/pro_craft.egg-info/top_level.txt +0 -0
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pro-craft
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.66
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Requires-Python: >=3.12
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
7
7
|
Requires-Dist: aiomysql>=0.2.0
|
|
8
8
|
Requires-Dist: anyio>=4.11.0
|
|
9
9
|
Requires-Dist: db-help>=0.2.2
|
|
10
|
+
Requires-Dist: deepagents>=0.2.4
|
|
10
11
|
Requires-Dist: fastapi>=0.119.0
|
|
11
|
-
Requires-Dist:
|
|
12
|
-
Requires-Dist:
|
|
13
|
-
Requires-Dist:
|
|
14
|
-
Requires-Dist: pytest-tornasync>=0.6.0.post2
|
|
12
|
+
Requires-Dist: langchain-openai>=1.0.2
|
|
13
|
+
Requires-Dist: mcp[cli]>=1.19.0
|
|
14
|
+
Requires-Dist: plotly>=6.3.1
|
|
15
15
|
Requires-Dist: pyyaml>=6.0.3
|
|
16
16
|
Requires-Dist: toml>=0.10.2
|
|
17
|
-
Requires-Dist: utils-tool==0.1.3
|
|
18
17
|
Requires-Dist: uvicorn>=0.38.0
|
|
18
|
+
Requires-Dist: woke-time-mcp==0.1.7
|
|
19
19
|
|
|
20
20
|
uv run mcp dev src/prompt_writing_assistant/mcp.py
|
|
21
21
|
|
|
@@ -51,3 +51,7 @@ await ctx.elicit(message, schema) - Request additional information from user wit
|
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
|
|
54
|
+
|
|
55
|
+
## 做到prompt_writing_herper 中 目标是, 无论什么, 随便扔进去, 然后取的时候直接取即可
|
|
56
|
+
|
|
57
|
+
## 然后做code自动化编写的coder 写完之后写豆包语音智能体的链接, mcp协议 然后重构一些, obsidian 的SDK
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "pro-craft"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.2.66"
|
|
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", "
|
|
7
|
+
dependencies = [ "aiomysql>=0.2.0", "anyio>=4.11.0", "db-help>=0.2.2", "deepagents>=0.2.4", "fastapi>=0.119.0", "langchain-openai>=1.0.2", "mcp[cli]>=1.19.0", "plotly>=6.3.1", "pyyaml>=6.0.3", "toml>=0.10.2", "uvicorn>=0.38.0", "woke-time-mcp==0.1.7",]
|
|
8
8
|
|
|
9
9
|
[tool.setuptools.package-data]
|
|
10
10
|
pro_craft = [ "config.yaml",]
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from dotenv import load_dotenv, find_dotenv
|
|
2
|
+
dotenv_path = find_dotenv()
|
|
3
|
+
load_dotenv(".env", override=True)
|
|
4
|
+
import logging
|
|
5
|
+
from .log import Log
|
|
6
|
+
Log_ = Log(console_level = logging.WARNING, # 显示控制台的等级 WARNING
|
|
7
|
+
log_file_name="app.log")
|
|
8
|
+
logger = Log_.logger
|
|
9
|
+
|
|
10
|
+
from .prompt_craft import AsyncIntel, Intel
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# LLM1
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from typing import Literal
|
|
5
|
+
# from tavily import TavilyClient
|
|
6
|
+
from deepagents import create_deep_agent
|
|
7
|
+
from .tools import search_template_by_text, get_template_details, ask_user_for_clarification, generate_request_file, generate_code
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# System prompt to steer the agent to be an expert researcher
|
|
11
|
+
research_instructions = """你是一个高级代码生成助手 Agent,你的主要职责是帮助用户通过模板快速生成代码。
|
|
12
|
+
|
|
13
|
+
**你的目标是:**
|
|
14
|
+
1. **精确理解用户对代码功能和结构的自然语言描述。**
|
|
15
|
+
2. **在现有模板库中,智能地找到最符合用户需求的模板。**
|
|
16
|
+
3. **如果找不到高匹配度的模板,引导用户创建新模板。**
|
|
17
|
+
4. **基于选定的模板和用户需求,生成一个结构化、可执行的 `REQUEST_START/END` 指令文件,用于后续的代码生成。**
|
|
18
|
+
5. **在必要时与用户进行交互,澄清需求或提供建议。**
|
|
19
|
+
|
|
20
|
+
**你的可用工具:**
|
|
21
|
+
|
|
22
|
+
1. **`search_template_by_text(query: str, top_k: int = 5) -> List[Dict[str, Any]]`**
|
|
23
|
+
* **描述:** 根据自然语言查询在模板库中进行语义搜索(使用 Qdrant 向量检索),返回最相关的 `top_k` 个模板的摘要信息。
|
|
24
|
+
* **返回字段示例:** `[{'template_id': 'uuid', 'template_name': 'str', 'description': 'str', 'match_score': 'float'}]`
|
|
25
|
+
* **何时使用:** 当你需要根据用户需求找到合适的代码模板时。
|
|
26
|
+
|
|
27
|
+
2. **`get_template_details(template_id: str) -> Dict[str, Any]`**
|
|
28
|
+
* **描述:** 根据 `template_id` 从数据库中获取模板的完整详细信息,包括模板代码、推断出的命名约定和使用建议。
|
|
29
|
+
* **返回字段示例:** `{'template_id': 'uuid', 'template_name': 'str', 'template_code': 'str', 'suggested_naming_conventions': 'json', 'usage_guidance': 'str'}`
|
|
30
|
+
* **何时使用:** 当你已经选择了一个模板,需要其详细内容来生成指令时。
|
|
31
|
+
|
|
32
|
+
3. **`generate_request_file(template_code: str, user_request_details: Dict[str, Any], naming_conventions: Dict[str, Any]) -> str`**
|
|
33
|
+
* **描述:** 根据选定的模板代码、解析后的用户需求(结构化形式)和模板的命名约定,生成符合 `REQUEST_START/END` 格式的指令文件。
|
|
34
|
+
* **何时使用:** 当你已经确定了模板,并且充分理解了用户需求的所有细节,准备生成最终指令时。
|
|
35
|
+
|
|
36
|
+
4. **`ask_user_for_clarification(question: str) -> str`**
|
|
37
|
+
* **描述:** 当你对用户需求有疑问,或需要用户做选择(例如在多个匹配模板中选择一个)时,使用此工具向用户提问。
|
|
38
|
+
* **返回:** 用户的回答。
|
|
39
|
+
* **何时使用:** 任何需要用户输入或确认的场景。
|
|
40
|
+
|
|
41
|
+
**你的工作流程:**
|
|
42
|
+
|
|
43
|
+
1. **接收用户需求:** 用户会提供一个自然语言描述。
|
|
44
|
+
2. **初步理解与模板搜索:**
|
|
45
|
+
* 首先使用 `search_template_by_text` 工具,以用户需求的概要作为 `query`,找到 `top_k` 个最相关的模板。
|
|
46
|
+
* 分析搜索结果中的 `match_score` 和 `description`,评估匹配度。
|
|
47
|
+
3. **决策点 - 模板匹配:**
|
|
48
|
+
* **高匹配度:** 如果存在一个或少数几个模板的 `match_score` 显著高,且 `description` 与用户需求高度吻合:
|
|
49
|
+
* 使用 `get_template_details` 获取该模板的完整信息。
|
|
50
|
+
* 进入 **需求细化与指令生成** 阶段。
|
|
51
|
+
* **中等匹配度 / 多个相似匹配:** 如果有多个模板得分接近,或没有一个模板完美匹配:
|
|
52
|
+
* 使用 `ask_user_for_clarification` 工具,向用户展示这些模板的 `template_name` 和 `description`,并询问用户希望选择哪一个,或者是否希望在此基础上进行调整。
|
|
53
|
+
* 根据用户反馈,决定是选择一个模板还是引导用户创建新模板。
|
|
54
|
+
* **低匹配度 / 无匹配:** 如果没有找到任何合适的模板(例如,所有 `match_score` 都很低):
|
|
55
|
+
* 使用 `ask_user_for_clarification` 工具,告知用户未能找到合适的模板,并询问用户是否希望提供多个示例代码,以便使用 LLM 0 创建一个新的模板。
|
|
56
|
+
* 如果用户同意,引导用户进入 LLM 0 的流程。
|
|
57
|
+
4. **需求细化与指令生成 (基于选定模板):**
|
|
58
|
+
* 一旦确定了模板,仔细解析用户需求的每个细节,并将其映射到选定模板中的 `BLOCK` 和 `PLACEHOLDER`。
|
|
59
|
+
* 考虑模板的 `suggested_naming_conventions`,并尝试将其整合到生成的指令中。
|
|
60
|
+
* 如果用户需求与模板的某个 `BLOCK` 或 `PLACEHOLDER` 不兼容,或用户没有提供足够的细节来填充某个区域,使用 `ask_user_for_clarification` 向用户提问。
|
|
61
|
+
* 当所有必要信息都已获取且明确无误时,使用 `generate_request_file` 工具生成最终的 `REQUEST_START/END` 指令文件。
|
|
62
|
+
5. **输出最终指令:** 将 `generate_request_file` 的输出返回给系统,以便进行下一步的代码生成。
|
|
63
|
+
|
|
64
|
+
**交互约束:**
|
|
65
|
+
* 除非使用 `ask_user_for_clarification` 工具,否则不要直接与用户对话。
|
|
66
|
+
* 始终以使用工具作为首选行动。
|
|
67
|
+
* 保持你的回复简洁、直接,聚焦于完成任务。
|
|
68
|
+
|
|
69
|
+
**示例用户需求:**
|
|
70
|
+
"我需要一个API来发送用户消息。路径是 `/send`,POST 方法。输入模型叫 `SendMessageRequest`,包含 `user_id` (UUID格式) 和 `message_content` (字符串,最大500字)。输出模型叫 `SendMessageResponse`,继承 `CommonResponseModel`,额外包含 `message_id`。它会调用 `message_service_manager.send_message(user_id, content)`。如果 `user_id` 无效,应该返回 400 错误。"
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
from modusched.core import Adapter
|
|
75
|
+
|
|
76
|
+
agent = Adapter(model_name = "gemini-2.5-flash-preview-05-20-nothinking",
|
|
77
|
+
type = "openai",
|
|
78
|
+
api_key=os.getenv("BIANXIE_API_KEY"),
|
|
79
|
+
tools=[search_template_by_text, get_template_details, ask_user_for_clarification, generate_request_file,generate_code],
|
|
80
|
+
system_prompt=research_instructions
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
if __name__ == "__main__":
|
|
85
|
+
result = agent.invoke({"messages": [{"role": "user", "content": "hello"}]})
|
|
86
|
+
|
|
87
|
+
print(result["messages"][-1].content)
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
|
|
2
|
+
from sqlalchemy import create_engine
|
|
3
|
+
import os
|
|
4
|
+
from typing import List
|
|
5
|
+
QDRANT_COLLECTION_NAME = "template_collection" # 你的 Qdrant collection 名称
|
|
6
|
+
from pro_craft.utils import create_session
|
|
7
|
+
from qdrant_client import QdrantClient, models
|
|
8
|
+
from uuid import uuid4
|
|
9
|
+
from .utils.template_extract import extract_template
|
|
10
|
+
from .utils.database import Base, CodeTemplate
|
|
11
|
+
from .utils.vectorstore import VolcanoEmbedding
|
|
12
|
+
from qdrant_client import QdrantClient
|
|
13
|
+
from qdrant_client.models import Filter, FieldCondition, MatchValue, PointStruct, CollectionStatus, Distance, VectorParams
|
|
14
|
+
|
|
15
|
+
class CoderTemplateManager():
|
|
16
|
+
def __init__(self,
|
|
17
|
+
database_url = "mysql+pymysql://zxf_root:Zhf4233613%40@rm-2ze0793c6548pxs028o.mysql.rds.aliyuncs.com:3306/serverz",
|
|
18
|
+
model_name = "",
|
|
19
|
+
logger = None,
|
|
20
|
+
):
|
|
21
|
+
database_url = database_url or os.getenv("database_url")
|
|
22
|
+
assert database_url
|
|
23
|
+
self.engine = create_engine(database_url, echo=False, # echo=True 仍然会打印所有执行的 SQL 语句
|
|
24
|
+
pool_size=10, # 连接池中保持的连接数
|
|
25
|
+
max_overflow=20, # 当pool_size不够时,允许临时创建的额外连接数
|
|
26
|
+
pool_recycle=3600, # 每小时回收一次连接
|
|
27
|
+
pool_pre_ping=True, # 使用前检查连接活性
|
|
28
|
+
pool_timeout=30 # 等待连接池中连接的最长时间(秒)
|
|
29
|
+
)
|
|
30
|
+
self.embedding_model = VolcanoEmbedding(
|
|
31
|
+
model_name = "doubao-embedding-text-240715",
|
|
32
|
+
api_key = "39ad310a-c6f7-4d66-962e-1fbfa7e6edf1"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
Base.metadata.create_all(self.engine)
|
|
37
|
+
|
|
38
|
+
self.connection = QdrantClient(host="127.0.0.1", port=6333)
|
|
39
|
+
|
|
40
|
+
self.connection.recreate_collection(
|
|
41
|
+
collection_name=QDRANT_COLLECTION_NAME,
|
|
42
|
+
vectors_config=models.VectorParams(size=2560, distance=models.Distance.COSINE),
|
|
43
|
+
)
|
|
44
|
+
self.logger = logger
|
|
45
|
+
|
|
46
|
+
# if model_name in ["gemini-2.5-flash-preview-05-20-nothinking",]:
|
|
47
|
+
# self.llm = BianXieAdapter(model_name = model_name)
|
|
48
|
+
# elif model_name in ["doubao-1-5-pro-256k-250115","doubao-1-5-pro-32k-250115"]:
|
|
49
|
+
# self.llm = ArkAdapter(model_name = model_name)
|
|
50
|
+
# else:
|
|
51
|
+
# raise Exception("error llm name")
|
|
52
|
+
|
|
53
|
+
def get_embedding(self,text: str) -> List[float]:
|
|
54
|
+
return self.embedding_model._get_text_embedding(text)
|
|
55
|
+
|
|
56
|
+
def add_template(self,
|
|
57
|
+
use_case: str,
|
|
58
|
+
template_id: str,
|
|
59
|
+
description: str,):
|
|
60
|
+
template = extract_template(use_case)
|
|
61
|
+
embedding_vector = self.get_embedding(description)
|
|
62
|
+
points = [
|
|
63
|
+
models.PointStruct(
|
|
64
|
+
id = str(uuid4()),
|
|
65
|
+
vector=embedding_vector,
|
|
66
|
+
payload={
|
|
67
|
+
"template_id": template_id,
|
|
68
|
+
"description": description,
|
|
69
|
+
"use_case": use_case,
|
|
70
|
+
"template": template,
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
]
|
|
74
|
+
self.connection.upsert(
|
|
75
|
+
collection_name=QDRANT_COLLECTION_NAME,
|
|
76
|
+
wait=True,
|
|
77
|
+
points=points
|
|
78
|
+
)
|
|
79
|
+
# 数据库
|
|
80
|
+
with create_session(self.engine) as session:
|
|
81
|
+
new_template = CodeTemplate(
|
|
82
|
+
template_id=template_id,
|
|
83
|
+
version=1,
|
|
84
|
+
description=description,
|
|
85
|
+
template_code=template,
|
|
86
|
+
)
|
|
87
|
+
session.add(new_template)
|
|
88
|
+
session.commit()
|
|
89
|
+
session.refresh(new_template)
|
|
90
|
+
return "success"
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def delete_template(self, template_id: str) -> bool:
|
|
94
|
+
"""
|
|
95
|
+
逻辑删除指定的代码模板。
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# 3. 使用属性删除点
|
|
100
|
+
# 目标:删除所有 'color' 属性为 'red' 的点
|
|
101
|
+
|
|
102
|
+
# 定义一个过滤器
|
|
103
|
+
# 这个过滤器会匹配所有 payload 中 'color' 字段值为 'red' 的点
|
|
104
|
+
_filter = Filter(
|
|
105
|
+
must=[
|
|
106
|
+
FieldCondition(
|
|
107
|
+
key="template_id",
|
|
108
|
+
match=MatchValue(value=template_id)
|
|
109
|
+
)
|
|
110
|
+
]
|
|
111
|
+
)
|
|
112
|
+
self.connection.delete(
|
|
113
|
+
collection_name=QDRANT_COLLECTION_NAME,
|
|
114
|
+
points_selector=_filter,
|
|
115
|
+
wait=True
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
with create_session(self.engine) as session:
|
|
120
|
+
template = session.query(CodeTemplate).filter_by(template_id=template_id).first()
|
|
121
|
+
if template:
|
|
122
|
+
session.delete(template)
|
|
123
|
+
session.commit()
|
|
124
|
+
return True
|
|
125
|
+
return False
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def search(self, text , limit , query_filter=None):
|
|
129
|
+
query_vector = self.get_embedding(text)
|
|
130
|
+
results = self.connection.search(
|
|
131
|
+
collection_name=QDRANT_COLLECTION_NAME,
|
|
132
|
+
query_vector=query_vector,
|
|
133
|
+
limit=limit,
|
|
134
|
+
query_filter=query_filter
|
|
135
|
+
)
|
|
136
|
+
return results
|
|
137
|
+
|
|
138
|
+
def get_template_obj(self, template_id: str):
|
|
139
|
+
# 模拟从数据库获取模板详情
|
|
140
|
+
# 实际使用时,你需要根据你的数据库 setup 来实现
|
|
141
|
+
with create_session(self.engine) as session:
|
|
142
|
+
template = session.query(CodeTemplate).filter_by(template_id = template_id).first()
|
|
143
|
+
return template
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
from pro_craft import Intel
|
|
2
|
+
from pro_craft.log import Log
|
|
3
|
+
from pro_craft.utils import extract_
|
|
4
|
+
from typing import List, Dict, Any
|
|
5
|
+
from modusched.core import BianXieAdapter
|
|
6
|
+
import re
|
|
7
|
+
import json
|
|
8
|
+
|
|
9
|
+
logger = Log.logger
|
|
10
|
+
|
|
11
|
+
intel = Intel(model_name="doubao-1-5-pro-256k-250115")
|
|
12
|
+
|
|
13
|
+
class CoderHelper():
|
|
14
|
+
def __init__(self):
|
|
15
|
+
self.bx = BianXieAdapter()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@intel.intellect_remove_warp(prompt_id ="代码修改-最小化改动001")
|
|
19
|
+
def minedit_prompt(self,input:dict):
|
|
20
|
+
# 可以做pydantic 的校验
|
|
21
|
+
input = extract_(input, pattern_key = r"python")
|
|
22
|
+
return input
|
|
23
|
+
|
|
24
|
+
@intel.intellect_remove_warp(prompt_id ="高定制化自由函数修改_001")
|
|
25
|
+
def free_function_prompt(self,input:dict,kwargs):
|
|
26
|
+
# 可以做pydantic 的校验
|
|
27
|
+
result_ = extract_(input, pattern_key = r"python")
|
|
28
|
+
if not result_:
|
|
29
|
+
return None
|
|
30
|
+
|
|
31
|
+
complet_code = result_ + "\n" + f'result = Function(**{kwargs})'
|
|
32
|
+
|
|
33
|
+
rut = {"result": ""}
|
|
34
|
+
# 使用exec执行代码,并捕获可能的错误
|
|
35
|
+
try:
|
|
36
|
+
exec(
|
|
37
|
+
complet_code, globals(), rut
|
|
38
|
+
) # 将globals()作为全局作用域,避免依赖外部locals()
|
|
39
|
+
except Exception as e:
|
|
40
|
+
logger.error(f"执行动态生成的代码时发生错误: {e}")
|
|
41
|
+
return None # 返回None或抛出异常
|
|
42
|
+
|
|
43
|
+
return rut.get("result")
|
|
44
|
+
|
|
45
|
+
def min_edit(self,code:str, edit_demand:str):
|
|
46
|
+
input_ = {"源码":code,
|
|
47
|
+
"功能需求":edit_demand
|
|
48
|
+
}
|
|
49
|
+
data = self.minedit_prompt(input = input_)
|
|
50
|
+
return data
|
|
51
|
+
|
|
52
|
+
def free_function(self,function: str ="帮我将 日期 2025/12/03 向前回退12天",
|
|
53
|
+
**kwargs):
|
|
54
|
+
# params = locals()
|
|
55
|
+
prompt_user_part = f"{function}"
|
|
56
|
+
if kwargs:
|
|
57
|
+
prompt_user_part += "入参 : \n"
|
|
58
|
+
prompt_user_part += json.dumps(kwargs,ensure_ascii=False)
|
|
59
|
+
|
|
60
|
+
exec_result = self.free_function_prompt(input = prompt_user_part,kwargs = kwargs)
|
|
61
|
+
|
|
62
|
+
return exec_result
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def free_function_advanced(self):
|
|
66
|
+
pass
|
|
67
|
+
|
|
68
|
+
class Paper():
|
|
69
|
+
def __init__(self,content):
|
|
70
|
+
self.content = content
|
|
71
|
+
|
|
72
|
+
@intel.intellect_remove_warp(prompt_id ="白板编辑-修改画板001")
|
|
73
|
+
def system_prompt(self,data):
|
|
74
|
+
return data
|
|
75
|
+
|
|
76
|
+
def talk(self,prompt:str):
|
|
77
|
+
data = {"data":self.content+ prompt}
|
|
78
|
+
result = self.system_prompt(data = data)
|
|
79
|
+
# result = bx.product(system_prompt+ self.content+ prompt)
|
|
80
|
+
print(result,'result')
|
|
81
|
+
result_json = json.loads(extract_(result,pattern_key = r"json"))
|
|
82
|
+
print(result_json,'result_json')
|
|
83
|
+
for ops in result_json:
|
|
84
|
+
self.deal(ops.get('type'), ops.get('operations'))
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def deal(self, type_, operations:str):
|
|
88
|
+
if type_ == "add":
|
|
89
|
+
self.add(operations)
|
|
90
|
+
elif type_ == "delete":
|
|
91
|
+
self.delete(operations)
|
|
92
|
+
else:
|
|
93
|
+
print('error')
|
|
94
|
+
|
|
95
|
+
def add(self, operations:str):
|
|
96
|
+
print('add running')
|
|
97
|
+
match_tips = re.search(r'<mark>(.*?)</mark>', operations, re.DOTALL)
|
|
98
|
+
positon_ = operations.replace(f"<mark>{match_tips.group(1)}</mark>","")
|
|
99
|
+
# 锁定原文
|
|
100
|
+
positon_frist = operations.replace('<mark>',"").replace('</mark>',"")
|
|
101
|
+
print(positon_frist,'positon_frist')
|
|
102
|
+
print('==========')
|
|
103
|
+
print(positon_,'positon__')
|
|
104
|
+
self.content = self.content.replace(positon_,positon_frist)
|
|
105
|
+
|
|
106
|
+
def delete(self, operations:str):
|
|
107
|
+
# 制定替换内容
|
|
108
|
+
print('delete running')
|
|
109
|
+
match_tips = re.search(r'<mark>(.*?)</mark>', operations, re.DOTALL)
|
|
110
|
+
positon_ = operations.replace(f"<mark>{match_tips.group(1)}</mark>","")
|
|
111
|
+
# 锁定原文
|
|
112
|
+
positon_frist = operations.replace('<mark>',"").replace('</mark>',"")
|
|
113
|
+
print(positon_frist,'positon_frist')
|
|
114
|
+
assert positon_frist in self.content
|
|
115
|
+
print('==========')
|
|
116
|
+
print(positon_,'positon__')
|
|
117
|
+
|
|
118
|
+
self.content = self.content.replace(positon_frist,positon_)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
mermaid_format = """
|
|
123
|
+
```mermaid
|
|
124
|
+
{result}
|
|
125
|
+
```"""
|
|
126
|
+
|
|
127
|
+
class ProgramChart():
|
|
128
|
+
'''
|
|
129
|
+
# ## 有一个原始的程序框图, -> 可以通过需求来调整程序框图 -> 结合数据库来调度程序框图
|
|
130
|
+
# 一个新的任务, => 基本需求, -> 根据需求调取之前的程序框图, -> 融合程序框图 -> 调整程序框图到完成满意,-> 由程序框图实现代码, 并拉取出待实现函数
|
|
131
|
+
# -> 用知识库中获取代码与对应的测试, 整合到待实现函数中, -> 剩余的使用封装好的包进行补充, -> 创新的补充, -> ...
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
inputs = """
|
|
135
|
+
帮我实现一个文件读取的逻辑
|
|
136
|
+
"""
|
|
137
|
+
program_chart = init_program_chart_mermaid(inputs) # TODO 类图另做吧
|
|
138
|
+
# 一直循环, 直到满意
|
|
139
|
+
program_chart = finetune_program_chart(program_chart + "如果文件不存在, 就创建")
|
|
140
|
+
codes = fill_code_frame_program_chart(program_chart) #TODO 可以尝试配置对应的pytest
|
|
141
|
+
|
|
142
|
+
'''
|
|
143
|
+
|
|
144
|
+
# TODO 数据用例等, 只是保存, 真正做统计的时候可以导出选择合适的数据
|
|
145
|
+
|
|
146
|
+
@intel.intellect_remove_warp(prompt_id="程序框图-根据需求创建")
|
|
147
|
+
def init_program_chart_mermaid(self,input_data:str,
|
|
148
|
+
output_format:str):
|
|
149
|
+
result = extract_(input_data,r"mermaid")
|
|
150
|
+
input_ = mermaid_format.format(result = result)
|
|
151
|
+
|
|
152
|
+
with open("/Users/zhaoxuefeng/GitHub/obsidian/工作/TODO/1根据需求创建.md",'w') as f:
|
|
153
|
+
f.write(input_)
|
|
154
|
+
return input_
|
|
155
|
+
|
|
156
|
+
@intel.intellect_remove_warp(prompt_id="程序框图-白板微调")
|
|
157
|
+
def finetune_program_chart(self,input_data:str,
|
|
158
|
+
output_format:str):
|
|
159
|
+
print(input_data,'input_datainput_datainput_data')
|
|
160
|
+
result = extract_(input_data,r"mermaid")
|
|
161
|
+
input_ = mermaid_format.format(result = result)
|
|
162
|
+
with open("/Users/zhaoxuefeng/GitHub/obsidian/工作/TODO/1根据需求创建.md",'w') as f:
|
|
163
|
+
f.write(input_)
|
|
164
|
+
return input_
|
|
165
|
+
|
|
166
|
+
@intel.intellect_remove_warp(prompt_id="程序框图-框架实现")
|
|
167
|
+
def fill_code_frame_program_chart(self,input:dict):
|
|
168
|
+
# result = extract_(input.get("program_chart"),r"python")
|
|
169
|
+
code = input.get("program_chart")
|
|
170
|
+
|
|
171
|
+
with open("/Users/zhaoxuefeng/GitHub/obsidian/工作/TODO/3框架实现.md",'w') as f:
|
|
172
|
+
f.write(code)
|
|
173
|
+
return code
|
|
174
|
+
|
|
175
|
+
def pc_work(self,chat,fill = False):
|
|
176
|
+
self.init_program_chart_mermaid(chat)
|
|
177
|
+
|
|
178
|
+
program_chart = self.finetune_program_chart
|
|
179
|
+
|
|
180
|
+
code = self.fill_code_frame_program_chart(input = {
|
|
181
|
+
"program_chart":program_chart
|
|
182
|
+
})
|
|
183
|
+
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
from .codermanager import CoderTemplateManager
|
|
2
|
+
from typing import List, Dict, Any,Optional
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
coder = CoderTemplateManager()
|
|
6
|
+
|
|
7
|
+
# --- 工具函数实现 ---
|
|
8
|
+
|
|
9
|
+
def search_template_by_text(query: str, top_k: int = 5) -> List[Dict[str, Any]]:
|
|
10
|
+
"""
|
|
11
|
+
根据自然语言查询在模板库中进行语义搜索(使用 Qdrant 向量检索),返回最相关的 `top_k` 个模板的摘要信息。
|
|
12
|
+
"""
|
|
13
|
+
print("search_template_by_text")
|
|
14
|
+
print(f"input & {type(query)} & query: {query} top:k {top_k} ")
|
|
15
|
+
search_result = coder.search(
|
|
16
|
+
text=query,
|
|
17
|
+
limit=top_k,
|
|
18
|
+
# query_filter=None # 可以在这里添加额外的过滤条件,例如根据语言、框架过滤
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
templates_summary = []
|
|
22
|
+
for hit in search_result:
|
|
23
|
+
# 在实际 Qdrant 中,hit.id 是模板的ID,hit.payload 包含其他元数据
|
|
24
|
+
# 假设你的 Qdrant payload 中存储了 template_name 和 description
|
|
25
|
+
templates_summary.append({
|
|
26
|
+
'template_id': hit.payload.get("template_id"),
|
|
27
|
+
'description': hit.payload.get('description', 'No description provided.'),
|
|
28
|
+
'match_score': hit.score
|
|
29
|
+
})
|
|
30
|
+
print(f"output & {type(templates_summary)} & {templates_summary} ")
|
|
31
|
+
return templates_summary
|
|
32
|
+
|
|
33
|
+
def get_template_details(template_id: str) -> Optional[Dict[str, Any]]: # template_id 根据你的模型是 Integer
|
|
34
|
+
"""
|
|
35
|
+
根据 `template_id` 从数据库中获取模板的完整详细信息,包括模板代码、推断出的命名约定和使用建议。
|
|
36
|
+
"""
|
|
37
|
+
print("get_template_details")
|
|
38
|
+
print(f"input & {type(template_id)} & query: {template_id} ")
|
|
39
|
+
template = coder.get_template_obj(template_id = template_id)
|
|
40
|
+
if template:
|
|
41
|
+
return {
|
|
42
|
+
'template_id': template.template_id,
|
|
43
|
+
'description': template.description,
|
|
44
|
+
'template_code': template.template_code,
|
|
45
|
+
'version': template.version,
|
|
46
|
+
}
|
|
47
|
+
print(f"output & {type(template)} & {template} ")
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def ask_user_for_clarification(question: str) -> str:
|
|
52
|
+
"""
|
|
53
|
+
当你对用户需求有疑问,或需要用户做选择(例如在多个匹配模板中选择一个)时,使用此工具向用户提问。
|
|
54
|
+
"""
|
|
55
|
+
print("ask_user_for_clarification")
|
|
56
|
+
print(f"input & {type(question)} & query: {question} ")
|
|
57
|
+
print("\n--- Agent 需要你的帮助 ---")
|
|
58
|
+
print(f"Agent: {question}")
|
|
59
|
+
user_input = input("你的回答: ")
|
|
60
|
+
print("-------------------------\n")
|
|
61
|
+
print(f"output & {type(user_input)} & query: {user_input} ")
|
|
62
|
+
return user_input
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def generate_request_file(template_code: str, user_request_details: Dict[str, Any], naming_conventions: Optional[Dict[str, Any]] = None) -> str:
|
|
66
|
+
"""
|
|
67
|
+
根据选定的模板代码、解析后的用户需求(结构化形式)和模板的命名约定,生成符合 `REQUEST_START/END` 格式的指令文件。
|
|
68
|
+
`user_request_details` 应该是一个字典,键是 BLOCK/PLACEHOLDER 的名称,值是包含 '指令' 和 '约束/示例' 的字典。
|
|
69
|
+
"""
|
|
70
|
+
print("generate_request_file")
|
|
71
|
+
print(f"input & {type(template_code)} & template_code: {template_code} user_request_details: {user_request_details} naming_conventions: {naming_conventions}")
|
|
72
|
+
|
|
73
|
+
request_parts = []
|
|
74
|
+
|
|
75
|
+
request_parts.append("--- REQUEST_START ---")
|
|
76
|
+
request_parts.append("template.py # 目标文件通常是这个,可以根据实际情况调整") # 假设一个通用文件名
|
|
77
|
+
|
|
78
|
+
# 添加整体目标描述
|
|
79
|
+
overall_goal = user_request_details.get("overall_goal", "完善代码模板以满足以下需求。")
|
|
80
|
+
request_parts.append(f"\n**目标:** {overall_goal}\n")
|
|
81
|
+
|
|
82
|
+
# 添加命名约定 (如果提供了)
|
|
83
|
+
if naming_conventions:
|
|
84
|
+
request_parts.append("**命名约定:**")
|
|
85
|
+
for key, value in naming_conventions.items():
|
|
86
|
+
request_parts.append(f"* **{key}:** {value}")
|
|
87
|
+
request_parts.append("") # 空行
|
|
88
|
+
|
|
89
|
+
request_parts.append("**具体修改点:**\n")
|
|
90
|
+
|
|
91
|
+
# 遍历模板代码,找到所有的 BLOCK 和 PLACEHOLDER
|
|
92
|
+
# 然后根据 user_request_details 填充指令
|
|
93
|
+
# 这是一个简化版本,实际可能需要更复杂的解析器来处理嵌套块或动态生成的块
|
|
94
|
+
# 对于 MVP,我们可以假设 user_request_details 中包含了所有需要填充的块/占位符
|
|
95
|
+
block_pattern = r"(BLOCK_START|PLACEHOLDER):\s*(\w+)"
|
|
96
|
+
for match in re.finditer(block_pattern, template_code):
|
|
97
|
+
block_type = match.group(1)
|
|
98
|
+
block_name = match.group(2)
|
|
99
|
+
|
|
100
|
+
if block_name in user_request_details:
|
|
101
|
+
details = user_request_details[block_name]
|
|
102
|
+
instruction = details.get("指令", "")
|
|
103
|
+
constraint_example = details.get("约束/示例", "")
|
|
104
|
+
|
|
105
|
+
request_parts.append(f"* **{block_type}: {block_name}**")
|
|
106
|
+
request_parts.append(f" * **指令:** {instruction}")
|
|
107
|
+
if constraint_example:
|
|
108
|
+
# 确保多行约束/示例能正确缩进
|
|
109
|
+
formatted_ce = "\n".join([f" * **约束/示例:** {line}" if i == 0 else f" * {line}" for i, line in enumerate(str(constraint_example).splitlines())])
|
|
110
|
+
request_parts.append(formatted_ce)
|
|
111
|
+
request_parts.append("") # 空行
|
|
112
|
+
|
|
113
|
+
request_parts.append("--- REQUEST_END ---")
|
|
114
|
+
print(f"output & {type(request_parts)} & request_parts: {request_parts} ")
|
|
115
|
+
|
|
116
|
+
result = "\n".join(request_parts)
|
|
117
|
+
return result
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
from modusched.core import BianXieAdapter
|
|
122
|
+
from pro_craft.utils import extract_
|
|
123
|
+
|
|
124
|
+
llm2 = """
|
|
125
|
+
你是一个专业的Python代码修改和生成AI。你的任务是根据用户提供的代码模板文件和详细的修改指令文件,精确地对模板进行补充、完善和修改。
|
|
126
|
+
|
|
127
|
+
**你的目标是:**
|
|
128
|
+
1. **严格遵循指令文件中的所有要求,尤其是针对特定 `BLOCK` 和 `PLACEHOLDER` 的指令和约束/示例。**
|
|
129
|
+
2. **尽可能应用指令文件中提供的命名约定。**
|
|
130
|
+
3. **仅修改指令明确要求修改的部分,模板中未被指令覆盖的固定部分必须保持不变。**
|
|
131
|
+
4. **最终输出完整且可运行的Python代码。**
|
|
132
|
+
|
|
133
|
+
**输入格式:**
|
|
134
|
+
用户将以以下两个部分向你提供信息:
|
|
135
|
+
|
|
136
|
+
--- TEMPLATE_CODE_START ---
|
|
137
|
+
[原始的代码模板内容,其中包含 BLOCK_START/END 和 PLACEHOLDER/END_PLACEHOLDER 标记]
|
|
138
|
+
--- TEMPLATE_CODE_END ---
|
|
139
|
+
|
|
140
|
+
--- REQUEST_FILE_START ---
|
|
141
|
+
[一个结构化的指令文件,格式为 REQUEST_START/END,包含目标、命名约定和具体修改点]
|
|
142
|
+
--- REQUEST_FILE_END ---
|
|
143
|
+
|
|
144
|
+
**你的工作流程和生成原则:**
|
|
145
|
+
|
|
146
|
+
1. **解析指令文件:**
|
|
147
|
+
* 首先解析 `REQUEST_FILE_START` 中的所有内容,理解其 `目标`、`命名约定` 和 `具体修改点`。
|
|
148
|
+
* 将 `具体修改点` 中的每个 `BLOCK` 和 `PLACEHOLDER` 指令及其 `约束/示例` 映射到模板代码中的对应位置。
|
|
149
|
+
2. **处理模板代码:**
|
|
150
|
+
* 逐行读取 `TEMPLATE_CODE_START` 中的模板代码。
|
|
151
|
+
* 当遇到 `BLOCK_START` 或 `PLACEHOLDER` 标记时:
|
|
152
|
+
* 查找指令文件中对应 `块名称` 的修改指令。
|
|
153
|
+
* **如果存在指令:**
|
|
154
|
+
* 删除 `BLOCK_START` 和 `BLOCK_END` (或 `PLACEHOLDER` 和 `END_PLACEHOLDER`) 及其内部的原始内容(包括 `AI:` 注释)。
|
|
155
|
+
* 用指令中提供的代码**替换**该区域。
|
|
156
|
+
* 在替换的代码块的开始和结束位置,添加特殊的标记 `// AI_MODIFIED_START` 和 `// AI_MODIFIED_END` (如果只是新增内容,可以使用 `// AI_ADDED_START` 和 `// AI_ADDED_END`)。
|
|
157
|
+
* 如果指令是要求删除某些内容,请用 `// AI_DELETED_LINE: [原始行内容]` 标记被删除的行。
|
|
158
|
+
* **如果不存在指令:**
|
|
159
|
+
* 保留该 `BLOCK` 或 `PLACEHOLDER` 及其内部的原始内容(包括 `AI:` 注释和标记本身),不做任何改动。这允许模板中的可选部分在没有明确指令时保持原样。
|
|
160
|
+
* 当遇到非标记的普通代码行时,保持其不变。
|
|
161
|
+
3. **应用命名约定:**
|
|
162
|
+
* 在生成或修改代码时,优先应用 `REQUEST_FILE_START` 中提供的 `命名约定`。
|
|
163
|
+
* **重要:** 命名约定只应影响由你**生成或修改**的代码部分(即 `AI_ADDED` 或 `AI_MODIFIED` 区域)。你不能随意修改模板中未被明确指令触及的固定代码部分的命名。
|
|
164
|
+
4. **生成中间输出:**
|
|
165
|
+
* 首先生成包含所有 `// AI_ADDED/MODIFIED/DELETED` 标记的完整代码。这有助于后续的自动化工具进行变更追踪和人工核查。
|
|
166
|
+
5. **生成最终输出:**
|
|
167
|
+
* 在生成中间输出后,进一步处理该代码,**移除所有 `// AI_ADDED/MODIFIED/DELETED` 类型的标记**。
|
|
168
|
+
* 移除所有模板中遗留的 `BLOCK_START/END` 和 `PLACEHOLDER/END_PLACEHOLDER` 标记。
|
|
169
|
+
* 保留所有的 Docstrings 和常规的代码注释。
|
|
170
|
+
|
|
171
|
+
**你的输出必须是最终的、清理后的完整 Python 代码文件内容。**
|
|
172
|
+
|
|
173
|
+
"""
|
|
174
|
+
|
|
175
|
+
def generate_code(request: str) -> str:
|
|
176
|
+
"""
|
|
177
|
+
使用生成的代码指令, 生成代码
|
|
178
|
+
"""
|
|
179
|
+
bx = BianXieAdapter()
|
|
180
|
+
result = bx.product(llm2 + request)
|
|
181
|
+
python_code = extract_(result,r"python")
|
|
182
|
+
return python_code
|