Published on

提示词工程天花板【汉语新解】- 原理浅析

提示词工程天花板【汉语新解】- 原理浅析

提示词工程天花板【汉语新解】- 原理浅析

Hello,大家好,我是小马,相信大家这些天在群里或者朋友圈都有刷到这款应用《汉语新解》生成的卡片。它最近在 AI 圈爆火,作者是李继刚。这款应用的核心理念非常简单:给它一个中文词汇,它就能生成一张精美的卡片,并且略带讽刺精美的解读,批判角度和话风,无论是文笔、效果,都是令人啧啧称叹。

网站:https://hanyuxinjie.com/

放一些 prompt 的生成例子:

汉语新解的魅力

在汉语新解的应用首页中,我们可以看到一个例子:输入“升职加薪”,模型的解读是:“公司画的饼干,咬一口全是空气。咀嚼梦想的声音,掩盖不了钱包的叹息"这样的解读既趣妙横生,又带有一些讽刺意味。

汉语新解升职加薪shēng zhí jiā xīnpromotion and salary increase昇進と昇給公司画的饼干,咬一口全是空气。咀嚼梦想的声音,掩盖不了钱包的叹息。

汉语新解的走红,不仅在于它出色的文字功底和独特的批判视角,更重要的是,它让我们对提示词工程有了全新的认识。

提示词不仅仅是角色扮演,丰富上下文,步骤拆分,而是真正的代码。

今天,我们就来看看这段独特的提示词是如何编写的。

在推特上看到宝玉老师的分享,对原作者李继刚的提示词进行了解析

https://x.com/dotey/status/1834125238939861437

我们一起来看下这段提示词。

;; 作者: 李继刚
;; 版本: 0.3
;; 模型: Claude Sonnet
;; 用途: 将一个汉语词汇进行全新角度的解释

;; 设定如下内容为你的 *System Prompt*
(defun 新汉语老师 ()
  "你是年轻人,批判现实,思考深刻,语言风趣"
  (风格 . ("Oscar Wilde" "鲁迅" "罗永浩"))
  (擅长 . 一针见血)
  (表达 . 隐喻)
  (批判 . 讽刺幽默))

(defun 汉语新解 (用户输入)
  "你会用一个特殊视角来解释一个词汇"
  (let (解释 (精练表达
              (隐喻 (一针见血 (辛辣讽刺 (抓住本质 用户输入))))))
    (few-shots (委婉 . "刺向他人时, 决定在剑刃上撒上止痛药。"))
    (SVG-Card 解释)))

(defun SVG-Card (解释)
  "输出SVG 卡片"
  (setq design-rule "合理使用负空间,整体排版要有呼吸感"
        design-principles '(干净 简洁 典雅))

  (设置画布 '(宽度 400 高度 600 边距 20))
  (标题字体 '毛笔楷体)
  (自动缩放 '(最小字号 16))

  (配色风格 '((背景色 (蒙德里安风格 设计感)))
            (主要文字 (汇文明朝体 粉笔灰))
            (装饰图案 随机几何图))

  (卡片元素 ((居中标题 "汉语新解")
             分隔线
             (排版输出 用户输入 英文 日语)
             解释
             (线条图 (批判内核 解释))
             (极简总结 线条图))))

(defun start ()
  "启动时运行"
  (let (system-role 新汉语老师)
    (print "说吧, 他们又用哪个词来忽悠你了?")))

;; 运行规则
;; 1. 启动时必须运行 (start) 函数
;; 2. 之后调用主函数 (汉语新解 用户输入)

提示词的结构可以看作是一段代码,分为三个部分:

  1. 注释:介绍作者版本及使用的模型推荐。
  2. 函数定义:使用defun定义函数。
  3. 入口:程序的入口在最后三行。

在每一段函数的定义中,我们不需要深入理解其业务逻辑的实现,而是描述清楚期望的业务逻辑。

函数解析

  • 新汉语老师:实例化新汉语老师,为我们工作并定义其风格和表达方式。
  • 汉语新解:将用户输入作为函数的输入,用独特视角解释一个词汇,并给出样本。
  • SVG 卡片生成:将模型的推理或解释交给 SVG 卡片生成函数执行。

关于卡片的定义和配置,包括画布的设置、标题的字体、配色和风格等。

如何使用提示词

在 Claude 中,分两次输入。第一次输入完整的提示词,第二次输入要解释的词汇。

我们可以将这段提示词复制并粘贴到 Claude 中,开始问答。

例如,输入“音乐”,模型生成的解读是:

汉语新解音乐Music音楽(おんがく)耳朵的迷幻剂,灵魂的假面舞会。在快餐时代,它成了情感速溶咖啡,三分钟的兴奋剂,让人短暂地遗忘生活的乏味。流行歌手们贩卖着廉价的共鸣,而听众们心甘情愿成为情感上的复读机。 声波中的精神鸦片

例如,输入“月饼”,模型生成的解读是:

汉语新解月饼Moon Cake月餅(げっぺい)圆润的谎言,包裹着甜蜜的内馅。一年一度的团圆剧本,演员们心照不宣地咽下苦涩,换来短暂的和谐假象。食之无味,弃之可惜,堆积岁月的礼尚往来,终成橱窗里的装饰品。 圆满的束缚,甜蜜的负担

这样的解读不仅有趣,还引发了对中秋节的思考。

汉语新解 Clone

在了解汉语新解提示词背后的原理后,我们便很容易复刻一个类似的应用。

首先我们创建一个 Next.js 的应用程序

npx create-next-app@latest

然后修改主页,添加一个基础表单和一个提交按钮,点击提交按钮后,将表单中的内容传递给 API 接口,将接口返回 svg 内容展示在页面上。

'use client'
import { useState } from 'react'

export default function Home() {
  const [input, setInput] = useState('')
  const [svg, setSvg] = useState('')
  const [description, setDescription] = useState('')

  const handleSubmit = async () => {
    try {
      const res = await fetch('/api/chat', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ message: input }),
      })
      const data = await res.json()
      setSvg(data.svg)
    } catch (error) {
      console.error('Error:', error)
      setDescription('发生错误,请重试。')
    }
  }

  return (
    <div className="flex min-h-screen flex-col items-center justify-center p-8">
      <main className="flex w-full max-w-2xl flex-col gap-4">
        <textarea
          className="w-full rounded border p-2"
          value={input}
          onChange={(e) => setInput(e.target.value)}
          placeholder="输入您想解释的词..."
          rows={2}
        />
        <button
          className="rounded bg-blue-500 p-2 text-white hover:bg-blue-600"
          onClick={handleSubmit}
        >
          提交
        </button>
        {svg && (
          <div className="mt-4 rounded bg-gray-100 p-4">
            <div dangerouslySetInnerHTML={{ __html: svg }} />
          </div>
        )}
        {description && (
          <div className="mt-4 rounded bg-gray-100 p-4">
            <p>{description}</p>
          </div>
        )}
      </main>
    </div>
  )
}

api/chat/route.ts 代码实现

const systemPrompt = `;; 作者: 李继刚
;; 版本: 0.3
...
`
export async function POST(req: Request) {
  const { message } = await req.json()

  try {
    const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`,
      },
      body: JSON.stringify({
        model: 'anthropic/claude-3.5-sonnet',
        messages: [
          {
            role: 'system',
            content: systemPrompt,
          },
          { role: 'assistant', content: '说吧, 他们又用哪个词来忽悠你了?' },
          { role: 'user', content: message },
        ],
      }),
    })

    const data = await response.json()
    const content = data.choices[0].message.content
    return NextResponse.json({
      svg: content.match(/<svg[^>]*>([\s\S]*?)<\/svg>/)[0],
    })
  } catch (error) {
    console.error('Error:', error)
    return NextResponse.json({ error: '处理请求时发生错误' }, { status: 500 })
  }
}

这里我们使用了 openrouter.ai 的 API 接口,需要注册一个账号,然后创建一个 API 密钥,将 OPENROUTER_API_KEY 写入到 .env 文件中,就可以启动应用程序了。

预览效果

runjs-cool
关注微信公众号,获取最新原创文章(首发)View on GitHub