diff --git a/.env b/.env index d15234a..aa38528 100644 --- a/.env +++ b/.env @@ -1,5 +1,5 @@ POSTGRES_USER=postgres -POSTGRES_PASSWORD=postgres +POSTGRES_PASSWORD=postgrespassword POSTGRES_HOST=127.0.0.1 POSTGRES_PORT=5432 POSTGRES_DB=pretor diff --git a/docs/problem.md b/docs/problem.md index d817906..ab8f2d7 100644 --- a/docs/problem.md +++ b/docs/problem.md @@ -2,23 +2,12 @@ --- ## 问题栏 #### 🔴 核心缺陷与修复 (Bug Fixes & Stability) -- [x] /pretor/core/individual每个template进行优化 -- [x] /pretor/worker_individual待完善复合子个体和基础子个体 + #### 🛡️ 安全与合规 (Security & Auth) -- [ ] 优化安全架构防止模型注入 -- [ ] 设计workflowEngine的自动扩缩容设计 -- [ ] 完善错误捕获和日志系统 #### ⚡ 性能与资源优化 (Performance & Scalability) -- [ ] 增加对应全workflow的情况追踪,使得在任务运行中人机交互更加自然方便 -- [ ] 优化import + #### 🏗️ 架构演进 (Architecture & Refactoring) -- [x] ~~使用fastapi-users完善用户系统~~(2026/4/19 fastapi-users会严重摧毁代码的优雅性) -- [x] 升级auth功能 -- [x] /pretor/api的接口函数进行重构 -- [x] /dockerfile待完善 -- [ ] 完善沙箱功能 -- [ ] 完善爬虫功能 -- [ ] 对接更多的provider + diff --git a/docs/project.md b/docs/project.md index f686e3f..da00f65 100644 --- a/docs/project.md +++ b/docs/project.md @@ -1,13 +1,5 @@ ## Pretor项目开发 -#项目规划 ---- -#### 全局规划: -- [ ] 实现监管模型的资源调度 -- [ ] 实现子个体的工作传递 -- [ ] 实现用户交互接口与ray集群的交互 -- [ ] 实现监管模型调度ray资源的接口 -- [ ] 实现由监管模型理解并发布,子个体向下布置任务,完成任务向上传递,监管模型检查的全工作流 ---- + #### 简介 **Pretor**是一款python开发,实现将小模型进行微调后整理为一个大型集群,从而实现低算力情况下高复杂度任务的实现。 系统模型分为以下部分: @@ -15,13 +7,6 @@ - **管控节点**:负责调度系统资源; - **意识节点**:负责复杂任务的处理; - **生长节点**:负责获取资源并且将基础模型训练为特化模型; -- **感知模块**:与外界交互的模型,如embedding模型,tts模型等; -- **复合子个体**:将监管节点的任务领取并进行专业的拆解任务并进行分配; -- **生产子个体**:领取任务最小单位并执行; ---- -#### 短期规划 -v0.1版本 -- [ ] **workflow构建**:构建任务的工作流 -- [ ] **接口构建**:对接vllm,openai接口和gemini接口 -- [ ] **工具构建**:配置供模型调用的爬虫工具箱,docker接口 -- [ ] **平台对接构建**:对接telegram等消息平台 \ No newline at end of file +- **特殊子个体**:与外界交互的模型,如embedding模型,tts模型等; +- **专家子个体**:; +- **基础子个体**:普通的agent对象; \ No newline at end of file diff --git a/frontend/src/components/Agent/WorkerIndividualSettings.tsx b/frontend/src/components/Agent/WorkerIndividualSettings.tsx index bba324b..c394e07 100644 --- a/frontend/src/components/Agent/WorkerIndividualSettings.tsx +++ b/frontend/src/components/Agent/WorkerIndividualSettings.tsx @@ -1,13 +1,14 @@ -import { useState } from 'react'; +import { useState, useEffect } from 'react'; import apiClient from '../../api/client'; import { Bot, Save } from 'lucide-react'; +import type { Provider } from '../../types'; -function WorkerIndividualForm() { +function WorkerIndividualForm({ providers }: { providers: Provider[] }) { const [formData, setFormData] = useState({ agent_name: '', agent_type: 'OrdinaryIndividual', description: '', - provider_title: '', + provider_title: providers.length > 0 ? providers[0].provider_title : '', model_id: '', system_prompt: '', output_template: '{}', @@ -17,6 +18,13 @@ function WorkerIndividualForm() { const [loading, setLoading] = useState(false); const [message, setMessage] = useState(''); + // Update initial provider_title when providers load + useEffect(() => { + if (providers.length > 0 && !formData.provider_title) { + setFormData(prev => ({ ...prev, provider_title: providers[0].provider_title })); + } + }, [providers, formData.provider_title]); + const handleChange = (e: React.ChangeEvent) => { setFormData({ ...formData, [e.target.name]: e.target.value }); }; @@ -74,7 +82,23 @@ function WorkerIndividualForm() {
- +
@@ -120,6 +144,25 @@ export function WorkerIndividualSettings() { const [modelId, setModelId] = useState(''); const [loading, setLoading] = useState(false); const [message, setMessage] = useState(''); + const [providers, setProviders] = useState([]); + + useEffect(() => { + const fetchProviders = async () => { + try { + const response = await apiClient.get('/api/v1/provider/list'); + const data = response.data.provider_list || {}; + const providerArray: Provider[] = Object.values(data); + setProviders(providerArray); + if (providerArray.length > 0) { + setProviderTitle(providerArray[0].provider_title); + } + } catch (error) { + console.error("Failed to fetch providers", error); + setProviders([]); + } + }; + fetchProviders(); + }, []); const handleCreateNode = async (e: React.FormEvent) => { e.preventDefault(); @@ -178,14 +221,22 @@ export function WorkerIndividualSettings() {
- setProviderTitle(e.target.value)} - placeholder="e.g. openai" required className="w-full px-4 py-2 border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" - /> + > + {providers.length === 0 ? ( + + ) : ( + providers.map((p) => ( + + )) + )} +
@@ -226,7 +277,7 @@ export function WorkerIndividualSettings() {

Add a new custom worker to the system.

- +
diff --git a/frontend/src/components/Resource/ResourceLayout.tsx b/frontend/src/components/Resource/ResourceLayout.tsx index d7b8c57..889c610 100644 --- a/frontend/src/components/Resource/ResourceLayout.tsx +++ b/frontend/src/components/Resource/ResourceLayout.tsx @@ -1,6 +1,7 @@ -import { Wrench, Database } from 'lucide-react'; +import { Wrench, Database, FileCode } from 'lucide-react'; import { SkillSettings } from './SkillSettings'; import { ResourceSettings } from './ResourceSettings'; +import { WorkflowTemplateSettings } from './WorkflowTemplateSettings'; interface ResourceLayoutProps { resourceTab: string; @@ -23,6 +24,13 @@ export function ResourceLayout({ resourceTab, setResourceTab }: ResourceLayoutPr Skills + + + + + + +
+
+

Installed Skills

+
+
+ {loading ? ( +
Loading skills...
+ ) : skills.length === 0 ? ( +
No skills installed yet.
+ ) : ( +
+ {skills.map((skill) => ( +
+
+
+ +
+ {skill} +
+ +
+ ))} +
+ )} +
); -} \ No newline at end of file +} diff --git a/frontend/src/components/Resource/WorkflowTemplateSettings.tsx b/frontend/src/components/Resource/WorkflowTemplateSettings.tsx new file mode 100644 index 0000000..3c259fa --- /dev/null +++ b/frontend/src/components/Resource/WorkflowTemplateSettings.tsx @@ -0,0 +1,150 @@ +import { useState, useEffect } from 'react'; +import apiClient from '../../api/client'; +import { FileCode, Trash2, Plus, LayoutTemplate } from 'lucide-react'; + +interface WorkflowTemplate { + name: string; + [key: string]: any; +} + +export function WorkflowTemplateSettings() { + const [templates, setTemplates] = useState>({}); + const [loading, setLoading] = useState(true); + const [templateJson, setTemplateJson] = useState('{\n "name": "my_template"\n}'); + const [creating, setCreating] = useState(false); + const [message, setMessage] = useState(''); + const [error, setError] = useState(''); + + const fetchTemplates = async () => { + setLoading(true); + try { + const response = await apiClient.get('/api/v1/resource/workflow_template'); + setTemplates(response.data.templates || {}); + } catch (err) { + console.error('Failed to fetch templates:', err); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + fetchTemplates(); + }, []); + + const handleCreate = async (e: React.FormEvent) => { + e.preventDefault(); + setCreating(true); + setMessage(''); + setError(''); + + try { + const parsedJson = JSON.parse(templateJson); + await apiClient.post('/api/v1/resource/workflow_template', parsedJson); + setMessage('Workflow template created successfully'); + setTemplateJson('{\n "name": "my_template"\n}'); + fetchTemplates(); + } catch (err: any) { + console.error(err); + if (err instanceof SyntaxError) { + setError('Invalid JSON format'); + } else { + setError(err.response?.data?.message || 'Failed to create workflow template'); + } + } finally { + setCreating(false); + } + }; + + const handleDelete = async (templateName: string) => { + if (!confirm(`Are you sure you want to delete ${templateName}?`)) return; + try { + await apiClient.delete(`/api/v1/resource/workflow_template/${templateName}`); + fetchTemplates(); + } catch (err: any) { + console.error('Failed to delete template:', err); + alert('Failed to delete template'); + } + }; + + return ( +
+
+

Workflow Templates

+

Manage and create reusable workflow templates.

+
+ +
+
+
+ +
+
+

Create Template

+

Provide the JSON definition for a new workflow template.

+
+
+
+
+
+ +