AI陪我做事 – 2 提示词工程技巧

提示工程无疑是开发 LLM 原生应用程序最关键的技能,因为制作正确的提示可以显著影响应用程序的性能和可靠性。⁤本文根据LLM 三角原则,介绍了八个实用的提示工程技巧,以提高您的 LLM 提示水平。

“LLM-Native 应用程序 10% 是复杂模型,90% 是实验数据驱动的工程工作。”

在本文中,我们将使用“登陆页面生成器”示例来演示如何应用每个技巧来增强现实世界的 LLM 应用程序。

AI陪我做事 - 2 提示词工程技巧
  1. 定义清晰的认知过程边界

首先定义每个代理或提示的目标。每个代理坚持一种认知过程类型,例如:概念化登录页面、选择组件或为特定部分生成内容。拥有明确的界限可以保持 LLM 交互的重点和清晰度,与LLM 三角原则的工程技术顶点保持一致。

“我们流程中的每个步骤都是一个独立的过程,必须完成这些步骤才能完成我们的任务。”

例如,避免在同一个提示中组合不同的认知过程,这可能会产生次优结果。相反,应将它们分解为单独的、有针对性的代理:

def  generate_landing_page_concept ( input_data: LandingPageInput ) -> LandingPageConcept:
    """
    根据输入数据生成登陆页面概念。
    此函数侧重于将登陆页面概念化的创作过程。
    """
    pass 

def  select_landing_page_components ( concept: LandingPageConcept ) -> List [LandingPageComponent]:
    """
    根据概念为登陆页面选择合适的组件。
    此函数仅负责选择组件,
    而不负责生成其内容或布局。
    """
    pass 

def  generate_component_content ( component: LandingPageComponent, concept: LandingPageConcept ) -> ComponentContent:
    """
    为特定登陆页面组件生成内容。
    此函数侧重于根据组件类型和整体概念创建合适的内容。
    """
    pass

通过为每个代理定义清晰的界限,我们可以确保工作流程中的每个步骤都针对特定的心理任务进行量身定制。这将提高输出质量,并使其更容易调试和改进。

2.明确指定输入/输出

定义清晰的输入和输出结构以反映目标并创建明确的数据模型。此实践涉及LLM 三角原则的工程技术和上下文数据顶点。

class LandingPageInput(BaseModel):
    brand: str
    product_desc: str
    campaign_desc: str
    cta_message: str
    target_audience: str
    unique_selling_points: List[str]

class LandingPageConcept(BaseModel):
    campaign_desc_reflection: str
    campaign_motivation: str
    campaign_narrative: str
    campaign_title_types: List[str]
    campaign_title: str
    tone_and_style: List[str]

这些Pydantic模型定义了我们的输入和输出数据的结构,并为代理定义了明确的界限和期望。

  1. 实施护栏

进行验证以确保 LLM 输出的质量和适度。Pydantic非常适合实施这些护栏,我们可以利用其原生功能来实现这一点。

class  LandingPageConcept ( BaseModel ):
    campaign_narrative: str = Field(..., min_length= 50 )   # 本机验证
    tone_and_style: List [ str ] = Field(..., min_items= 2 )   # 本机验证

    # ...其余字段... # 

    @field_validator( "campaign_narrative" )
    @classmethod
    def  validate_campaign_narrative ( cls, v ):
        """使用另一个 AI 模型根据内容政策验证活动叙述。"""
         response = client.moderations.create( input =v) 

        if response.results[ 0 ].flagged:
            raise ValueError( "提供的文本违反了内容政策。" ) 

        return v

在此示例中,通过定义两种类型的验证器来确保我们的应用程序的质量:

使用 PydanitcField定义简单的验证,例如至少 2 个语气/风格属性,或叙述中至少 50 个字符

使用自定义方式field_validator 确保生成的叙述符合我们的内容审核政策(使用人工智能)

  1. 与人类认知过程保持一致

通过将复杂的任务分解为遵循逻辑顺序的较小步骤,构建您的 LLM 工作流程以模仿人类的认知过程。为此,请遵循LLM 三角原则的SOP(标准操作程序)指导原则。

“如果没有 SOP,即使是最强大的 LLM 也无法持续提供高质量的结果。”

4.1 捕捉隐藏的隐性认知跳跃

在我们的示例中,我们期望模型返回LandingPageConcept结果。通过要求模型输出某些字段,我们以类似于人类营销人员或设计师创建登陆页面概念的方式指导 LLM。

class LandingPageConcept(BaseModel):
    campaign_desc_reflection: str  # Encourages analysis of the campaign description
    campaign_motivation: str       # Prompts thinking about the 'why' behind the campaign
    campaign_narrative: str        # Guides creation of a cohesive story for the landing page
    campaign_title_types: List[str]# Promotes brainstorming different title approaches
    campaign_title: str            # The final decision on the title
    tone_and_style: List[str]      # Defines the overall feel of the landing page

这种LandingPageConcept结构鼓励 LLM 遵循类似人类的推理过程,反映专家本能地做出的微妙的心理飞跃(隐性认知“跳跃” ),就像我们在 SOP 中建模的那样。

4.2 将复杂流程分解为多个步骤/代理

对于复杂的任务,将流程分解为多个步骤,每个步骤由单独的 LLM 调用或“代理”处理:

async  def  generate_landing_page ( input_data: LandingPageInput ) -> LandingPageOutput:
    # 步骤 1:概念化活动
    concept = await generate_concept(input_data) 
    # 步骤 2:选择适当的组件
    selected_components = await select_components(concept) 
    # 步骤 3:为每个选定的组件生成内容
    component_contents = {
        component: await generate_component_content(input_data, concept, component)
        for component in selected_components
    } 
    # 步骤 4:编写最终 HTML
     html = await compose_html(concept, component_contents) 
    return LandingPageOutput(concept, selected_components, component_contents, html)

这种多智能体方法与人类解决复杂问题的方式相一致——将问题分解为更小的部分。

AI陪我做事 - 2 提示词工程技巧
  1. 利用结构化数据(YAML)

YAML是一种流行的人性化数据序列化格式。它旨在方便人类阅读,同时又易于机器解析 – 这使得它成为 LLM 的经典用途。

我发现 YAML 对于 LLM 交互特别有效,并且在不同的模型中产生更好的结果。它将标记处理重点放在有价值的内容上,而不是语法上。

YAML 在不同的 LLM 提供商之间也更具可移植性,并且允许您维护结构化的输出格式。

async def generate_component_content(input_data: LandingPageInput, concept: LandingPageConcept,component: LandingPageComponent) -> ComponentContent:
    few_shots = {
        LandingPageComponent.HERO: {
            "input": LandingPageInput(
                brand="Mustacher",
                product_desc="Luxurious mustache cream for grooming and styling",
                # ... rest of the input data ...
            ),
            "concept": LandingPageConcept(
                campaign_title="Celebrate Dad's Dash of Distinction",
                tone_and_style=["Warm", "Slightly humorous", "Nostalgic"]
                # ... rest of the concept ...
            ),
            "output": ComponentContent(
                motivation="The hero section captures attention and communicates the core value proposition.",
                content={
                    "headline": "Honor Dad's Distinction",
                    "subheadline": "The Art of Mustache Care",
                    "cta_button": "Shop Now"
                }
            )
        },
        # Add more component examples as needed
    }

    sys = "Craft landing page component content. Respond in YAML with motivation and content structure as shown."
    
    messages = [{"role": "system", "content": sys}]
    messages.extend([
        message for example in few_shots.values() for message in [
            {"role": "user", "content": to_yaml({"input": example["input"], "concept": example["concept"], "component": component.value})},
            {"role": "assistant", "content": to_yaml(example["output"])}
        ]
    ])
    messages.append({"role": "user", "content": to_yaml({"input": input_data, "concept": concept, "component": component.value})})

    response = await client.chat.completions.create(model="gpt-4o", messages=messages)
    raw_content = yaml.safe_load(sanitize_code_block(response.choices[0].message.content))
    return ComponentContent(**raw_content)

请注意,我们使用少量示例来“展示而不是讲述”预期的 YAML 格式。这种方法比提示输出结构的明确说明更有效。

  1. 精心制作上下文数据

仔细考虑如何建模并向 LLM 呈现数据。此技巧是LLM 三角原则中情境数据顶点的核心。

“即使是最强大的模型也需要相关且结构良好的上下文数据才能发挥作用。”

不要丢弃模型上的所有数据。相反,要向模型提供与你定义的目标相关的信息。

async def select_components(concept: LandingPageConcept) -> List[LandingPageComponent]:
    sys_template = jinja_env.from_string("""
    Your task is to select the most appropriate components for a landing page based on the provided concept.
    Choose from the following components:
    {% for component in components %}
    - {{ component.value }}
    {% endfor %}
    You MUST respond ONLY in a valid YAML list of selected components.
    """)

    sys = sys_template.render(components=LandingPageComponent)

    prompt = jinja_env.from_string("""
    Campaign title: "{{ concept.campaign_title }}"
    Campaign narrative: "{{ concept.campaign_narrative }}"
    Tone and style attributes: {{ concept.tone_and_style | join(', ') }}
    """)

    messages = [{"role": "system", "content": sys}] + few_shots + [
        {"role": "user", "content": prompt.render(concept=concept)}]

    response = await client.chat.completions.create(model="gpt-4", messages=messages)

    selected_components = yaml.safe_load(response.choices[0].message.content)
    return [LandingPageComponent(component) for component in selected_components]

在此示例中,我们使用Jinja模板动态编写提示。这可以优雅地为每个 LLM 交互创建有针对性和相关的上下文。

“数据为 LLM 本土应用提供了动力。背景数据的战略设计释放了其真正的潜力。”

6.1 利用小样本学习的力量

少量学习是快速工程中必不可少的技术。为 LLM 提供相关示例可显著提高其对任务的理解。

请注意,在下面讨论的两种方法中,我们都将 Pydantic 模型重用于少数样本——此技巧可确保示例与我们的实际任务之间的一致性!

6.1.1 小样本学习示例

看一下few_shots第 5 节中的字典。采用这种方法:

示例将作为单独的用户和助手消息添加到messages列表中,然后是实际的用户输入。

messages.extend([
    message for example in few_shots for message in [
        {"role": "user", "content": to_yaml(example["input"])},
        {"role": "assistant", "content": to_yaml(example["output"])}
    ]
])
# then we can add the user prompt
messages.append({"role": "user", "content": to_yaml(input_data)})

通过将示例放置为messages,我们与教学模型的训练方法保持一致。它允许模型在处理用户输入之前看到多个“示例交互”——帮助它理解预期的输入输出模式。

随着应用程序的发展,您可以添加更多小样本以覆盖更多用例。对于更高级的应用程序,请考虑实施动态小样本选择,根据当前输入选择最相关的示例。

6.1.2 特定任务的小样本学习

此方法使用提示本身中与当前任务直接相关的示例。例如,此提示模板用于生成其他独特卖点:

Generate {{ num_points }} more unique selling points for our {{ brand }} {{ product_desc }}, following this style:
{% for point in existing_points %}
- {{ point }}
{% endfor %}

通过将示例直接包含在提示中而不是作为单独的消息,这为特定的内容生成任务提供了有针对性的指导。

  1. KISS — 保持简单,愚蠢

虽然“思维树”或“思维图”等花哨的即时工程技术很有趣,尤其是对于研究而言,但我发现它们非常不切实际,而且对于生产来说往往是过度的。对于实际应用,重点是设计适当的 LLM 架构(又称工作流工程)。

这延伸到了 LLM 应用程序中代理的使用。了解标准代理和自主代理之间的区别至关重要:

代理: “通过执行 XYZ 操作带我从 A 到达 B。”

自主代理: “通过做某事带我从 A 到 B,我不在乎怎么做。”

虽然自主代理提供了灵活性和更快的开发速度,但它们也可能带来不可预测性和调试挑战。谨慎使用自主代理 — 只有当其好处明显超过潜在的失控和复杂性增加时才使用。

8.迭代,迭代,迭代!

持续的实验对于改进你的 LLM 原生应用程序至关重要。不要被实验的想法吓倒——它们可以小到调整提示。正如“构建 LLM 应用程序:清晰的分步指南”中所述,建立基准并跟踪改进至关重要 。

与“人工智能”中的其他一切一样,LLM 原生应用程序需要研究和实验思维

另一个很好的技巧是在比你打算在生产中使用的模型更弱的模型上尝试你的提示(例如开源 8B 模型)

——在较小模型上表现“还可以”的提示在较大的模型上会表现得更好。

这个行为有点类似于软件开发时代,将程序运行在性能较差的机器上验证性能问题的方式一样。这样硬件性能好的机器就基本不会有明显的性能问题了。

结论

这八个技巧为 LLM 原生应用程序中有效的提示工程奠定了坚实的基础。通过在提示中应用这些技巧,您将能够创建更可靠、更高效、更可扩展的 LLM 原生应用程序。

请记住,我们的目标不是创建最复杂的系统,而是构建在现实世界中可以运行的东西。继续尝试、学习和构建 — 可能性是无穷无尽的。

AI陪我做事 - 2 提示词工程技巧

RA/SD 衍生者AI训练营。发布者:稻草人,转载请注明出处:https://www.shxcj.com/ai%e9%99%aa%e6%88%91%e5%81%9a%e4%ba%8b-2-%e6%8f%90%e7%a4%ba%e8%af%8d%e5%b7%a5%e7%a8%8b%e6%8a%80%e5%b7%a7/

(0)
上一篇 18小时前
下一篇 2024-12-03 8:35 下午

相关推荐

发表回复

登录后才能评论
本文授权以下站点有原版访问授权 https://www.shxcj.com https://www.2img.ai https://www.2video.cn