Nichengjin
Clean commit without faiss cache
a23394a
Raw
History Blame Contribute Delete
7.18 kB
import click
from pathlib import Path
from datetime import datetime
from jinja2 import Template
from typing import Optional
from dataflow_agent.logger import get_logger
log = get_logger(__name__)
TEMPLATE_DIR = Path(__file__).parent / "templates"
# ---------- util ----------
def to_snake(s: str) -> str:
import re
s = re.sub(r'[\- ]+', '_', s).strip('_')
parts = re.split(r'[_]', s)
return '_'.join(p.lower() for p in parts if p)
def to_camel(s: str) -> str:
return ''.join(p.capitalize() for p in to_snake(s).split('_'))
# ---------- CLI ----------
@click.group()
def cli():
"""DataFlow-Agent command line."""
pass
@cli.command("create")
@click.option("--wf_name", help="要创建的 workflow 名称")
@click.option("--agent_name", help="要创建的 agent 名称")
@click.option("--gradio_name", help="要创建的 gradio page 名称")
@click.option("--prompt_name", help="要创建的 prompt template 名称")
@click.option("--agent_as_tool_name", help="要创建的 agent-as-tool 名称")
@click.option("--state_name", help="要创建的 state 名称")
def create_artifact(wf_name: Optional[str] = None,
agent_name: Optional[str] = None,
gradio_name: Optional[str] = None,
prompt_name: Optional[str] = None,
agent_as_tool_name: Optional[str] = None,
state_name: Optional[str] = None):
"""
dfa create --wf_name xxx
dfa create --agent_name yyy
dfa create --gradio_name zzz
dfa create --prompt_name zzz
dfa create --agent_as_tool_name aaa
dfa create --state_name bbb
"""
opts = [bool(wf_name), bool(agent_name), bool(gradio_name), bool(prompt_name), bool(agent_as_tool_name), bool(state_name)]
if sum(opts) != 1:
click.echo(" --wf_name / --agent_name / --gradio_name / --prompt_name / --agent_as_tool_name / --state_name 必须且只能选一个", err=True)
raise SystemExit(1)
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# ------------------------------------------------------------------
# 1. Workflow
# ------------------------------------------------------------------
if wf_name:
wf_name_snake = to_snake(wf_name)
# 1.1 workflow 源码
wf_dest = Path(__file__).parent / "workflow" / f"wf_{wf_name_snake}.py"
wf_tpl_path = TEMPLATE_DIR / "workflow.py.jinja"
wf_context = dict(
wf_name=wf_name,
wf_name_snake=wf_name_snake,
entry="step1",
timestamp=timestamp,
)
_generate_file(wf_dest, wf_tpl_path, wf_context, "workflow")
# 1.2 对应测试
project_root = Path(__file__).parent.parent
test_dest = project_root / "tests" / f"test_{wf_name_snake}.py"
test_tpl = TEMPLATE_DIR / "test_workflow.py.jinja"
test_ctx = dict(
wf_name=wf_name,
wf_name_snake=wf_name_snake,
timestamp=timestamp,
)
_generate_file(test_dest, test_tpl, test_ctx, "test")
# ------------------------------------------------------------------
# 2. Agent
# ------------------------------------------------------------------
elif agent_name:
agent_snake = to_snake(agent_name)
dest = Path(__file__).parent / "agentroles" / "common_agents" / f"{agent_snake}_agent.py"
tpl_path = TEMPLATE_DIR / "agent.py.jinja"
ctx = dict(
agent_name=agent_name,
agent_name_snake=agent_snake,
agent_name_camel=to_camel(agent_name),
timestamp=timestamp,
)
_generate_file(dest, tpl_path, ctx, "agent")
# ------------------------------------------------------------------
# 3. Gradio Page
# ------------------------------------------------------------------
elif gradio_name:
page_snake = to_snake(gradio_name)
project_root = Path(__file__).parent.parent
dest = project_root / "gradio_app" / "pages" / f"page_{page_snake}.py"
tpl_path = TEMPLATE_DIR / "gradio_page.py.jinja"
ctx = dict(
page_name=gradio_name,
page_name_snake=page_snake,
timestamp=timestamp,
)
_generate_file(dest, tpl_path, ctx, "gradio page")
# ------------------------------------------------------------------
# 4. Prompt Template
# ------------------------------------------------------------------
elif prompt_name:
prompt_snake = to_snake(prompt_name)
dest = Path(__file__).parent / "promptstemplates" / "resources" / f"pt_{prompt_snake}_repo.py"
tpl_path = TEMPLATE_DIR / "prompt_repo.py.jinja"
ctx = dict(
prompt_name=prompt_name,
prompt_name_snake=prompt_snake,
prompt_name_camel=to_camel(prompt_name),
timestamp=timestamp,
)
_generate_file(dest, tpl_path, ctx, "prompt template")
# ------------------------------------------------------------------
# 5. Agent-as-Tool
# ------------------------------------------------------------------
elif agent_as_tool_name:
agent_snake = to_snake(agent_as_tool_name)
dest = Path(__file__).parent / "agentroles" / "common_agents" / f"{agent_snake}_agent.py"
tpl_path = TEMPLATE_DIR / "agent_as_tool_name.py.jinja"
ctx = dict(
agent_name=agent_as_tool_name,
agent_name_snake=agent_snake,
agent_name_camel=to_camel(agent_as_tool_name),
timestamp=timestamp,
)
_generate_file(dest, tpl_path, ctx, "agent-as-tool")
# ------------------------------------------------------------------
# 6. State
# ------------------------------------------------------------------
else:
state_snake = to_snake(state_name)
dest = Path(__file__).parent / "states" / f"{state_snake}_state.py"
tpl_path = TEMPLATE_DIR / "state_name.py.jinja"
ctx = dict(
state_name=state_name,
state_name_snake=state_snake,
state_name_camel=to_camel(state_name),
timestamp=timestamp,
)
_generate_file(dest, tpl_path, ctx, "state")
# ---------- helper ----------
def _generate_file(dest: Path, tpl_path: Path, context: dict, file_type: str):
"""
通用文件生成函数
"""
dest.parent.mkdir(parents=True, exist_ok=True)
if dest.exists():
# click.echo(f" {dest} 已存在,跳过生成")
log.error(f" {dest} 已存在,跳过生成")
return
if not tpl_path.exists():
log.error(f" 模板不存在: {tpl_path}", err=True)
raise SystemExit(1)
rendered = Template(tpl_path.read_text(encoding="utf-8")).render(**context)
dest.write_text(rendered, encoding="utf-8")
try:
rel_path = dest.relative_to(Path.cwd())
except ValueError:
rel_path = dest
log.critical(f" 已生成 {file_type}: {rel_path}")
if __name__ == "__main__":
cli()