Skip to content

Begin 组件

概述

Begin组件是RAGFlow工作流的入口组件,每个工作流必须包含至少一个Begin组件。它负责初始化工作流执行,设置欢迎信息,并为后续组件提供初始上下文。

主要功能

  • 🚀 工作流入口点和启动器
  • 💬 可配置的开场白和欢迎信息
  • 📝 支持变量替换和动态内容
  • 🔗 为下游组件提供初始数据流

适用场景

  • 聊天机器人的欢迎语设置
  • 工作流的说明和引导
  • 初始化上下文变量
  • 多轮对话的开始节点

参数配置

基础参数

参数名类型必填默认值说明
prologuestring""开场白文本内容

详细说明

prologue (开场白)

  • 类型: 字符串
  • 描述: 工作流开始时显示的欢迎信息或说明文本
  • 支持功能:
    • 普通文本内容
    • Markdown格式支持
    • 变量替换(如用户名、时间等)
    • 表情符号和特殊字符
  • 字符限制: 最大5000字符
  • 示例:
    您好!👋 我是您的AI助手,很高兴为您服务。
    
    我可以帮助您:
    - 📚 搜索和分析文档内容
    - 💡 回答专业问题
    - 🔍 查找相关信息
    
    请告诉我您需要什么帮助?

输入输出

输入

Begin组件作为工作流入口,不接受任何上游输入

输出格式

json
{
  "content": "开场白文本内容",
  "component_id": "begin_组件ID",
  "timestamp": "2024-01-12T10:30:00Z",
  "reference": []
}

输出字段说明

  • content: 配置的开场白文本
  • component_id: 组件的唯一标识符
  • timestamp: 执行时间戳
  • reference: 引用信息(Begin组件通常为空)

前端配置界面

配置表单

typescript
interface BeginFormData {
  prologue: string;  // 开场白内容
}

界面元素

  • 开场白编辑器: 多行文本输入框,支持Markdown预览
  • 变量插入: 支持插入预定义变量(用户名、时间等)
  • 字符计数: 实时显示字符数量和限制
  • 预览功能: 实时预览渲染效果

使用示例

示例1: 简单欢迎语

json
{
  "component_name": "Begin",
  "params": {
    "prologue": "欢迎使用智能问答系统!请输入您的问题。"
  }
}

示例2: 详细说明文档

json
{
  "component_name": "Begin",
  "params": {
    "prologue": "# 📋 企业知识库助手\n\n您好!我是企业知识库智能助手,可以帮助您:\n\n## 🔍 主要功能\n- 搜索公司文档和政策\n- 回答业务流程问题\n- 提供技术支持信息\n- 查找联系人和部门信息\n\n## 💡 使用建议\n- 请用具体的关键词描述您的问题\n- 可以询问具体的产品、流程或政策名称\n- 如需人工协助,请输入"转人工"\n\n现在请告诉我您需要什么帮助?"
  }
}

示例3: 角色扮演助手

json
{
  "component_name": "Begin",
  "params": {
    "prologue": "🎭 **AI法律顾问** 为您服务\n\n我是您的专业法律咨询助手,具备以下专业能力:\n\n✅ **专业领域**:\n- 合同法律事务\n- 劳动法咨询\n- 知识产权保护\n- 公司法务支持\n\n⚠️ **重要声明**:\n本助手提供的信息仅供参考,不构成正式法律建议。重要法律事务请咨询专业律师。\n\n请描述您遇到的法律问题,我将为您提供专业的初步分析。"
  }
}

前端实现

节点组件

typescript
// web/src/pages/flow/canvas/node/begin-node.tsx
export function BeginNode({ id, data, isConnectable, selected }: NodeProps) {
  return (
    <section className={`${styles.ragNode} ${selected ? styles.selectedNode : ''}`}>
      {/* 只有输出连接点,没有输入 */}
      <Handle
        type="source"
        position={Position.Right}
        isConnectable={isConnectable}
        className={styles.handle}
      />
      
      <NodeHeader id={id} name={data.name} label={data.label} />
      
      <div className={styles.nodeBody}>
        <div className={styles.nodeInfo}>
          <Icon component={PlayCircleOutlined} className={styles.nodeIcon} />
          <span className={styles.nodeDescription}>工作流入口</span>
        </div>
        
        {data.form.prologue && (
          <div className={styles.prologuePreview}>
            {data.form.prologue.length > 50 
              ? `${data.form.prologue.substring(0, 50)}...`
              : data.form.prologue
            }
          </div>
        )}
      </div>
    </section>
  );
}

配置表单

typescript
// web/src/pages/flow/form/begin-form/index.tsx
const BeginForm: React.FC<IOperatorForm> = ({ onValuesChange, form }) => {
  const [characterCount, setCharacterCount] = useState(0);
  const [showPreview, setShowPreview] = useState(false);

  const handlePrologueChange = useCallback((e) => {
    const value = e.target.value;
    setCharacterCount(value.length);
    onValuesChange({ prologue: value }, { prologue: value });
  }, [onValuesChange]);

  return (
    <Form form={form} layout="vertical" onValuesChange={onValuesChange}>
      <Form.Item
        name="prologue"
        label={
          <Space>
            <span>开场白</span>
            <Tooltip title="支持Markdown格式,可以包含表情符号">
              <InfoCircleOutlined />
            </Tooltip>
          </Space>
        }
        extra={
          <Space>
            <span style={{ color: '#666' }}>
              {characterCount}/5000 字符
            </span>
            <Switch
              checkedChildren="预览"
              unCheckedChildren="编辑"
              checked={showPreview}
              onChange={setShowPreview}
            />
          </Space>
        }
      >
        {showPreview ? (
          <div className={styles.markdownPreview}>
            <ReactMarkdown>{form.getFieldValue('prologue') || ''}</ReactMarkdown>
          </div>
        ) : (
          <Input.TextArea
            rows={8}
            placeholder="请输入开场白内容,支持Markdown格式..."
            showCount
            maxLength={5000}
            onChange={handlePrologueChange}
          />
        )}
      </Form.Item>

      <Form.Item label="变量插入">
        <Space wrap>
          <Button size="small" onClick={() => insertVariable('{{user_name}}')}>
            用户名
          </Button>
          <Button size="small" onClick={() => insertVariable('{{current_time}}')}>
            当前时间
          </Button>
          <Button size="small" onClick={() => insertVariable('{{workflow_name}}')}>
            工作流名称
          </Button>
        </Space>
      </Form.Item>
    </Form>
  );
};

后端实现

参数类

python
# agent/component/begin.py
class BeginParam(ComponentParamBase):
    """Begin组件参数"""
    
    def __init__(self):
        super().__init__()
        self.prologue = ""  # 开场白
        
    def check(self):
        """参数验证"""
        # Begin组件的prologue是可选的,所以不需要严格验证
        if len(self.prologue) > 5000:
            raise ValueError("开场白长度不能超过5000字符")
        
    def get_openai_message(self):
        """为LLM调用生成消息(如果需要)"""
        if self.prologue:
            return [{"role": "assistant", "content": self.prologue}]
        return []

组件类

python
class Begin(ComponentBase):
    """Begin组件实现"""
    
    component_name = "Begin"
    
    def _run(self, history, **kwargs):
        """
        执行Begin组件逻辑
        
        Args:
            history: 对话历史(通常为空,因为Begin是起点)
            **kwargs: 额外参数,可能包含用户信息等
            
        Returns:
            pd.DataFrame: 包含开场白的输出数据
        """
        # 处理变量替换
        prologue_content = self._process_variables(self._param.prologue, **kwargs)
        
        # 如果没有配置开场白,使用默认欢迎语
        if not prologue_content.strip():
            prologue_content = "您好!我是您的AI助手,请问有什么可以帮助您的吗?"
        
        # 返回标准格式的DataFrame
        return pd.DataFrame([{
            "content": prologue_content,
            "component_id": self._id,
            "timestamp": datetime.now().isoformat(),
            "message_type": "greeting",
            "reference": []
        }])
    
    def _process_variables(self, content, **kwargs):
        """
        处理内容中的变量替换
        """
        import re
        from datetime import datetime
        
        # 定义可用变量
        variables = {
            'user_name': kwargs.get('user_name', '用户'),
            'current_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'workflow_name': kwargs.get('workflow_name', '智能助手'),
            'current_date': datetime.now().strftime('%Y年%m月%d日'),
            'greeting': self._get_time_based_greeting()
        }
        
        # 替换变量
        for var_name, var_value in variables.items():
            pattern = f'{{{{\\s*{var_name}\\s*}}}}'
            content = re.sub(pattern, str(var_value), content)
        
        return content
    
    def _get_time_based_greeting(self):
        """
        根据时间返回不同的问候语
        """
        from datetime import datetime
        
        hour = datetime.now().hour
        
        if 5 <= hour < 12:
            return "早上好"
        elif 12 <= hour < 18:
            return "下午好"
        elif 18 <= hour < 22:
            return "晚上好"
        else:
            return "夜深了"

最佳实践

1. 开场白设计原则

  • 简洁明了: 避免过长的介绍,突出核心功能
  • 角色定位: 明确助手的身份和能力范围
  • 引导用户: 提供使用建议和示例问题
  • 设置期望: 说明系统能力和限制

2. 内容组织建议

markdown
# 推荐的开场白结构

## 1. 问候和身份介绍(必需)
您好!我是[角色名称],很高兴为您服务。

## 2. 核心功能说明(推荐)
我可以帮助您:
- 功能1
- 功能2  
- 功能3

## 3. 使用建议(可选)
💡 **使用提示**
- 建议1
- 建议2

## 4. 重要声明(如需要)
⚠️ **注意事项**
- 免责声明
- 使用限制

## 5. 引导开始(推荐)
请告诉我您需要什么帮助?

3. 变量使用技巧

json
{
  "prologue": "{{greeting}}!{{user_name}},欢迎使用{{workflow_name}}。\n\n今天是{{current_date}},我将为您提供专业的咨询服务。\n\n请描述您的需求:"
}

4. 多场景适配

  • 客服场景: 强调服务态度和可解决问题
  • 知识问答: 突出知识库范围和查询能力
  • 技术支持: 说明技术领域和解决方案类型
  • 创意协作: 展示创作能力和合作方式

常见问题

Q1: Begin组件可以有多个吗?

A: 可以。工作流中可以有多个Begin组件,但至少需要一个。多个Begin组件通常用于:

  • 不同的入口场景(如新用户vs老用户)
  • A/B测试不同的开场白
  • 多角色的对话系统

Q2: 开场白支持HTML格式吗?

A: 不支持HTML,但支持Markdown格式,可以实现丰富的文本样式。

Q3: 如何在开场白中添加图片?

A: 可以使用Markdown图片语法:

markdown
![图片描述](图片URL)

Q4: Begin组件的输出可以被多个下游组件使用吗?

A: 可以。Begin组件的输出可以连接到多个下游组件,实现分支处理。

Q5: 变量替换失败怎么办?

A: 如果变量不存在或格式错误,系统会保留原始文本。建议:

  • 使用标准的变量名称
  • 检查花括号格式
  • 在测试环境验证变量替换效果

相关组件

推荐搭配组件

  • Categorize: 根据用户首次输入进行分类路由
  • Message: 处理和格式化用户消息
  • Template: 基于用户输入生成动态响应

典型工作流模式

Begin → Categorize → [不同处理路径]
Begin → Message → Retrieval → Generate → Answer
Begin → Template → Generate → Answer

组件版本: v1.0.0
最后更新: 2025-01-12