Chuyển đến nội dung chính

第 22 課:工作流程自動化 — 聊天機器人觸發的工作流程與流程編排

聊天機器人觸發的工作流程、審批流程、與 n8n/Temporal 整合、事件驅動的自動化、人機互動工作流程、長期運作的流程。

🏗️ 建築 — 第 22 課 第 22 課:工作流程自動化 — 聊天機器人觸發的工作流程與流程 編排

企業人工智慧聊天機器人平台架構-從原型到生產

第六部分:高階人工智慧能力

亞洲開發網

1. 聊天機器人觸發的工作流程-概述

聊天機器人企業不只是回答問題——它應該 執行業務流程。從「建立 Jira 票證」、「批准休假申請」到「入職新員工」—您所需的一切 工作流程引擎 堅強的背後。


┌─────────── WORKFLOW ARCHITECTURE ─────────────────────┐
│                                                       │
│  User: "Tạo đơn xin nghỉ phép 3 ngày từ thứ 2"      │
│                     │                                 │
│              ┌──────▼──────┐                          │
│              │  AI Engine  │                          │
│              │  (Extract   │                          │
│              │   intent)   │                          │
│              └──────┬──────┘                          │
│                     │                                 │
│              ┌──────▼──────────────────┐              │
│              │  WORKFLOW ORCHESTRATOR  │              │
│              │  ┌──────────────────┐   │              │
│              │  │ 1. Validate      │   │              │
│              │  │    leave balance  │   │              │
│              │  │ 2. Create request │   │              │
│              │  │ 3. Notify manager│   │              │
│              │  │ 4. Wait approval │   │              │
│              │  │ 5. Update HR sys │   │              │
│              │  │ 6. Confirm user  │   │              │
│              │  └──────────────────┘   │              │
│              └──────┬──────────────────┘              │
│                     │                                 │
│          ┌──────────┼──────────┐                      │
│          ▼          ▼          ▼                       │
│     ┌────────┐ ┌────────┐ ┌────────┐                  │
│     │  HR    │ │ Slack  │ │ Email  │                   │
│     │ System │ │ Notify │ │ Notify │                   │
│     └────────┘ └────────┘ └────────┘                   │
└───────────────────────────────────────────────────────┘

2. 工作流引擎設計


// Workflow Definition DSL
interface WorkflowDefinition {
  id: string;
  name: string;
  trigger: WorkflowTrigger;
  steps: WorkflowStep[];
  timeout: string; // ISO 8601 duration
  onError: ErrorHandler;
}

interface WorkflowStep {
  id: string;
  name: string;
  type: 'action' | 'condition' | 'approval' | 'wait' | 'parallel';
  config: StepConfig;
  onSuccess?: string; // Next step ID
  onFailure?: string;
}

// Workflow Engine
class WorkflowEngine {
  constructor(
    private readonly store: WorkflowStore,
    private readonly executor: StepExecutor,
    private readonly eventBus: EventBus,
  ) {}

  async startWorkflow(
    definitionId: string,
    input: Record<string, unknown>,
    context: WorkflowContext,
  ): Promise<WorkflowInstance> {
    const definition = await this.store.getDefinition(definitionId);

    // Create instance
    const instance: WorkflowInstance = {
      id: crypto.randomUUID(),
      definitionId,
      status: 'running',
      input,
      context,
      currentStepId: definition.steps[0].id,
      state: {},
      startedAt: new Date(),
      history: [],
    };

    await this.store.saveInstance(instance);

    // Start execution
    await this.executeNextStep(instance, definition);

    return instance;
  }

  private async executeNextStep(
    instance: WorkflowInstance,
    definition: WorkflowDefinition,
  ): Promise<void> {
    const step = definition.steps.find(
      s => s.id === instance.currentStepId,
    );
    if (!step) {
      await this.completeWorkflow(instance, 'completed');
      return;
    }

    // Log history
    instance.history.push({
      stepId: step.id,
      stepName: step.name,
      startedAt: new Date(),
      status: 'running',
    });

    try {
      switch (step.type) {
        case 'action':
          await this.executeAction(instance, step);
          break;
        case 'condition':
          await this.evaluateCondition(instance, step, definition);
          break;
        case 'approval':
          await this.requestApproval(instance, step);
          return; // Pauses here — resumes on approval event
        case 'wait':
          await this.scheduleResume(instance, step);
          return; // Pauses here — resumes on timer
        case 'parallel':
          await this.executeParallel(instance, step);
          break;
      }

      // Move to next step
      instance.currentStepId = step.onSuccess ?? null;
      await this.store.saveInstance(instance);

      if (instance.currentStepId) {
        await this.executeNextStep(instance, definition);
      } else {
        await this.completeWorkflow(instance, 'completed');
      }
    } catch (error) {
      await this.handleStepError(instance, step, error);
    }
  }

  // Resume workflow when approval comes in
  async handleApproval(
    instanceId: string,
    approved: boolean,
    approvedBy: string,
  ): Promise<void> {
    const instance = await this.store.getInstance(instanceId);
    const definition = await this.store.getDefinition(instance.definitionId);
    const step = definition.steps.find(
      s => s.id === instance.currentStepId,
    );

    // Update history
    const historyEntry = instance.history.find(
      h => h.stepId === step.id && h.status === 'running',
    );
    if (historyEntry) {
      historyEntry.status = approved ? 'approved' : 'rejected';
      historyEntry.completedAt = new Date();
      historyEntry.metadata = { approvedBy };
    }

    // Route based on approval result
    instance.currentStepId = approved ? step.onSuccess : step.onFailure;
    instance.state.approvalResult = { approved, approvedBy };
    await this.store.saveInstance(instance);

    if (instance.currentStepId) {
      await this.executeNextStep(instance, definition);
    } else {
      await this.completeWorkflow(
        instance,
        approved ? 'completed' : 'rejected',
      );
    }
  }
}

3. 預建工作流程模板


// Leave Request Workflow
const leaveRequestWorkflow: WorkflowDefinition = {
  id: 'leave-request',
  name: 'Đơn xin nghỉ phép',
  trigger: { type: 'chatbot', intent: 'request_leave' },
  timeout: 'P7D', // 7 days
  steps: [
    {
      id: 'validate',
      name: 'Kiểm tra số ngày phép còn lại',
      type: 'action',
      config: {
        action: 'hr.checkLeaveBalance',
        input: { employeeId: '{{context.userId}}' },
      },
      onSuccess: 'create_request',
      onFailure: 'insufficient_leave',
    },
    {
      id: 'insufficient_leave',
      name: 'Thông báo hết phép',
      type: 'action',
      config: {
        action: 'chatbot.sendMessage',
        input: {
          message: 'Bạn chỉ còn {{state.remainingDays}} ngày phép. '
            + 'Không đủ cho {{input.days}} ngày yêu cầu.',
        },
      },
    },
    {
      id: 'create_request',
      name: 'Tạo đơn nghỉ phép',
      type: 'action',
      config: {
        action: 'hr.createLeaveRequest',
        input: {
          employeeId: '{{context.userId}}',
          startDate: '{{input.startDate}}',
          days: '{{input.days}}',
          reason: '{{input.reason}}',
        },
      },
      onSuccess: 'notify_manager',
    },
    {
      id: 'notify_manager',
      name: 'Gửi thông báo cho quản lý',
      type: 'action',
      config: {
        action: 'notification.send',
        input: {
          channel: 'slack',
          recipient: '{{state.managerId}}',
          message: '{{context.userName}} xin nghỉ phép {{input.days}} ngày.',
          actions: [
            { label: 'Approve', value: 'approve' },
            { label: 'Reject', value: 'reject' },
          ],
        },
      },
      onSuccess: 'wait_approval',
    },
    {
      id: 'wait_approval',
      name: 'Chờ phê duyệt',
      type: 'approval',
      config: {
        approvers: ['{{state.managerId}}'],
        timeout: 'P3D', // 3 days
        escalateTo: '{{state.hrDirectorId}}',
      },
      onSuccess: 'update_hr',
      onFailure: 'notify_rejected',
    },
    {
      id: 'update_hr',
      name: 'Cập nhật hệ thống HR',
      type: 'action',
      config: {
        action: 'hr.approveLeave',
        input: { requestId: '{{state.requestId}}' },
      },
      onSuccess: 'confirm_user',
    },
    {
      id: 'confirm_user',
      name: 'Xác nhận cho nhân viên',
      type: 'action',
      config: {
        action: 'chatbot.sendMessage',
        input: {
          message: 'Đơn nghỉ phép đã được duyệt! '
            + 'Bạn nghỉ từ {{input.startDate}}, {{input.days}} ngày.',
        },
      },
    },
    {
      id: 'notify_rejected',
      name: 'Thông báo từ chối',
      type: 'action',
      config: {
        action: 'chatbot.sendMessage',
        input: {
          message: 'Đơn nghỉ phép bị từ chối. Lý do: {{state.rejectionReason}}',
        },
      },
    },
  ],
  onError: {
    action: 'chatbot.sendMessage',
    input: { message: 'Có lỗi xảy ra khi xử lý đơn. Vui lòng thử lại sau.' },
  },
};

4. 時間整合-持久的工作流程


import { proxyActivities, executeChild, sleep } from '@temporalio/workflow';

// Temporal Workflow for long-running processes
export async function employeeOnboardingWorkflow(
  input: OnboardingInput,
): Promise<OnboardingResult> {
  const { createAccounts, sendNotifications, setupEquipment, hrActivities }
    = proxyActivities<OnboardingActivities>({
      startToCloseTimeout: '10 minutes',
      retry: { maximumAttempts: 3 },
    });

  // Step 1: Create accounts in parallel
  const [emailAccount, slackAccount, jiraAccount] = await Promise.all([
    createAccounts.createEmail(input.employee),
    createAccounts.createSlack(input.employee),
    createAccounts.createJira(input.employee),
  ]);

  // Step 2: Setup equipment (may take days)
  const equipmentRequest = await setupEquipment.requestLaptop(input.employee);

  // Step 3: Notify chatbot — user gets progress updates
  await sendNotifications.notifyChatbot({
    userId: input.requesterId,
    message: `Accounts created. Equipment request #${equipmentRequest.id} submitted.`,
  });

  // Step 4: Wait for equipment delivery (durable timer)
  await sleep('3 days');

  // Step 5: Check equipment status
  const equipmentStatus = await setupEquipment.checkStatus(equipmentRequest.id);

  // Step 6: Schedule orientation
  const orientation = await hrActivities.scheduleOrientation({
    employeeId: input.employee.id,
    startDate: input.startDate,
  });

  // Step 7: Child workflow — training plan
  const trainingCompletion = await executeChild(
    trainingPlanWorkflow,
    { args: [{ employeeId: input.employee.id, role: input.employee.role }] },
  );

  return {
    employee: input.employee,
    accounts: { emailAccount, slackAccount, jiraAccount },
    equipment: equipmentStatus,
    orientation,
    trainingCompleted: trainingCompletion,
  };
}

5. 聊天機器人 ↔ 工作流程橋


class ChatbotWorkflowBridge {
  constructor(
    private readonly workflowEngine: WorkflowEngine,
    private readonly intentMapper: IntentToWorkflowMapper,
  ) {}

  // Map chatbot intent to workflow
  async handleIntent(
    intent: string,
    parameters: Record<string, unknown>,
    context: ChatContext,
  ): Promise<WorkflowResponse> {
    const workflowId = this.intentMapper.getWorkflow(intent);
    if (!workflowId) {
      return { type: 'no_workflow', message: 'No workflow mapped for this intent.' };
    }

    // Check if user has pending workflow of same type
    const pending = await this.workflowEngine.findPendingWorkflow(
      context.userId,
      workflowId,
    );
    if (pending) {
      return {
        type: 'existing_workflow',
        message: `Bạn đã có yêu cầu đang xử lý (ID: ${pending.id}). `
          + `Trạng thái: ${pending.status}`,
        workflow: pending,
      };
    }

    // Start new workflow
    const instance = await this.workflowEngine.startWorkflow(
      workflowId,
      parameters,
      {
        userId: context.userId,
        tenantId: context.tenantId,
        conversationId: context.conversationId,
        channel: context.channel,
      },
    );

    return {
      type: 'workflow_started',
      message: `Yêu cầu đã được tạo (ID: ${instance.id}). `
        + `Tôi sẽ cập nhật tiến trình cho bạn.`,
      workflow: instance,
    };
  }

  // Handle workflow status check from chatbot
  async checkWorkflowStatus(
    userId: string,
    workflowId?: string,
  ): Promise<string> {
    const workflows = workflowId
      ? [await this.workflowEngine.getInstance(workflowId)]
      : await this.workflowEngine.getUserWorkflows(userId);

    if (workflows.length === 0) {
      return 'Bạn không có yêu cầu nào đang xử lý.';
    }

    return workflows.map(w => {
      const current = w.history.filter(h => h.status === 'completed').length;
      const total = w.history.length;
      return `📋 ${w.definitionId} (ID: ${w.id})\n`
        + `   Trạng thái: ${w.status}\n`
        + `   Tiến trình: ${current}/${total} steps\n`
        + `   Bước hiện tại: ${w.currentStepId}`;
    }).join('\n\n');
  }
}

6. 事件驅動的自動化


class EventDrivenAutomation {
  constructor(
    private readonly eventBus: EventBus,
    private readonly workflowEngine: WorkflowEngine,
    private readonly chatbot: ChatbotService,
  ) {
    this.registerAutomations();
  }

  private registerAutomations(): void {
    // Auto-trigger workflow on specific events
    this.eventBus.on('ticket.created', async (event) => {
      // Auto-assign based on category
      if (event.data.priority === 'critical') {
        await this.workflowEngine.startWorkflow('critical-escalation', {
          ticketId: event.data.ticketId,
          category: event.data.category,
        }, { userId: 'system', tenantId: event.data.tenantId });
      }
    });

    // Proactive notification automation
    this.eventBus.on('deployment.completed', async (event) => {
      // Notify relevant users via chatbot
      const subscribers = await this.getDeploymentSubscribers(
        event.data.service,
      );
      for (const userId of subscribers) {
        await this.chatbot.sendProactiveMessage(userId, {
          text: `🚀 Service "${event.data.service}" deployed v${event.data.version}`,
          actions: [
            { label: 'View changelog', action: 'view_changelog', data: event.data },
            { label: 'Rollback', action: 'rollback', data: event.data },
          ],
        });
      }
    });

    // SLA breach automation
    this.eventBus.on('sla.warning', async (event) => {
      await this.workflowEngine.startWorkflow('sla-escalation', {
        ticketId: event.data.ticketId,
        remainingMinutes: event.data.remainingMinutes,
        assignee: event.data.assignee,
      }, { userId: 'system', tenantId: event.data.tenantId });
    });
  }
}

第 22 課總結

  • 工作流程引擎:具有動作、條件、批准、等待、平行步驟的狀態機方法
  • 審批流程:暫停工作流程 → 通知審核者 → 復原審核事件
  • 時間整合:適用於長時間運作流程(數天/數週)的耐用工作流程
  • 聊天機器人橋:映射意圖→工作流程、檢查狀態、傳送進度更新
  • 事件驅動:自動觸發業務事件的工作流程(票證、部署、SLA)

下一篇: GPU 基礎架構與模型服務 — 自寄 LLM 部署、vLLM/TGI、GPU 叢集管理、模型快取、自動擴充推理。