Files
pages/2024/07/03/ai-summary.html
2025-12-31 16:00:29 +00:00

592 lines
64 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>使用Cloudflare Workers制作博客AI摘要 | Mayx的博客</title>
<meta name="generator" content="Jekyll v3.9.5" />
<meta property="og:title" content="使用Cloudflare Workers制作博客AI摘要" />
<meta name="author" content="mayx" />
<meta property="og:locale" content="zh_CN" />
<meta name="description" content="Cloudflare实在是太强了以至于全都依赖它了😂" />
<meta property="og:description" content="Cloudflare实在是太强了以至于全都依赖它了😂" />
<meta property="og:site_name" content="Mayx的博客" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2024-07-03T00:00:00+08:00" />
<meta name="twitter:card" content="summary" />
<meta property="twitter:title" content="使用Cloudflare Workers制作博客AI摘要" />
<meta name="google-site-verification" content="huTYdEesm8NaFymixMNqflyCp6Jfvd615j5Wq1i2PHc" />
<meta name="msvalidate.01" content="0ADFCE64B3557DC4DC5F2DC224C5FDDD" />
<meta name="yandex-verification" content="fc0e535abed800be" />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"mayx"},"dateModified":"2024-07-03T00:00:00+08:00","datePublished":"2024-07-03T00:00:00+08:00","description":"Cloudflare实在是太强了以至于全都依赖它了😂","headline":"使用Cloudflare Workers制作博客AI摘要","mainEntityOfPage":{"@type":"WebPage","@id":"/2024/07/03/ai-summary.html"},"publisher":{"@type":"Organization","logo":{"@type":"ImageObject","url":"https://avatars0.githubusercontent.com/u/17966333"},"name":"mayx"},"url":"/2024/07/03/ai-summary.html"}</script>
<!-- End Jekyll SEO tag -->
<link rel="canonical" href="https://mabbs.github.io/2024/07/03/ai-summary.html" />
<link type="application/atom+xml" rel="alternate" href="/atom.xml" title="Mayx的博客" />
<link rel="alternate" type="application/rss+xml" title="Mayx的博客(RSS)" href="/rss.xml" />
<link rel="alternate" type="application/json" title="Mayx的博客(JSON Feed)" href="/feed.json" />
<link rel="stylesheet" href="/assets/css/style.css?v=1767196818" />
<!--[if !IE]> -->
<link rel="stylesheet" href="/Live2dHistoire/live2d/css/live2d.css" />
<!-- <![endif]-->
<link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="Mayx的博客" />
<link rel="webmention" href="https://webmention.io/mabbs.github.io/webmention" />
<link rel="pingback" href="https://webmention.io/mabbs.github.io/xmlrpc" />
<link rel="preconnect" href="https://summary.mayx.eu.org" crossorigin="anonymous" />
<link rel="prefetch" href="https://www.blogsclub.org/badge/mabbs.github.io" as="image" />
<link rel="blogroll" type="text/xml" href="/blogroll.opml" />
<link rel="me" href="https://github.com/Mabbs" />
<script src="/assets/js/jquery.min.js"></script>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-ajaxtransport-xdomainrequest/1.0.3/jquery.xdomainrequest.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
<script>
var lastUpdated = new Date("Thu, 01 Jan 2026 00:00:18 +0800");
var BlogAPI = "https://summary.mayx.eu.org";
</script>
<script src="/assets/js/main.js"></script>
<!--[if !IE]> -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async="async" src="https://www.googletagmanager.com/gtag/js?id=UA-137710294-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-137710294-1');
</script>
<script src="/assets/js/instant.page.js" type="module"></script>
<!-- <![endif]-->
</head>
<body>
<!--[if !IE]> --><noscript><marquee style="top: -15px; position: relative;"><small>发现当前浏览器没有启用JavaScript这不影响你的浏览但可能会有一些功能无法使用……</small></marquee></noscript><!-- <![endif]-->
<!--[if IE]><marquee style="top: -15px; position: relative;"><small>发现当前浏览器为Internet Explorer这不影响你的浏览但可能会有一些功能无法使用……</small></marquee><![endif]-->
<div class="wrapper">
<header class="h-card">
<h1><a class="u-url u-uid p-name" rel="me" href="/">Mayx的博客</a></h1>
<img src="https://avatars0.githubusercontent.com/u/17966333" fetchpriority="high" class="u-photo" alt="Logo" style="width: 90%; max-width: 300px; max-height: 300px;" />
<p class="p-note">Mayx's Home Page</p>
<form action="/search.html">
<input type="text" name="keyword" id="search-input-all" placeholder="Search blog posts.." />&#160;<input type="submit" value="搜索" />
</form>
<br />
<p class="view"><a class="u-url" href="/Mabbs/">About me</a></p>
<ul class="downloads">
<li style="width: 270px; border-right: none;"><a href="/MayxBlog.tgz">Download <strong>TGZ File</strong></a></li>
</ul>
</header>
<section class="h-entry">
<small><time class="date dt-published" datetime="2024-07-03T00:00:00+08:00">3 July 2024</time> - 字数统计8423 - 阅读大约需要32分钟 - Hits: <span id="/2024/07/03/ai-summary.html" class="visitors">Loading...</span></small>
<h1 class="p-name">使用Cloudflare Workers制作博客AI摘要</h1>
<p class="view">by <a class="p-author h-card" href="//github.com/Mabbs">mayx</a></p>
<div id="outdate" style="display:none;">
<hr /><p>
这是一篇创建于 <span id="outime"></span> 天前的文章,其中的信息可能已经有所发展或是发生改变。
</p>
</div>
<script>
daysold = Math.floor((new Date().getTime() - new Date("Wed, 03 Jul 2024 00:00:00 +0800").getTime()) / (24 * 60 * 60 * 1000));
if (daysold > 90) {
document.getElementById("outdate").style.display = "block";
document.getElementById("outime").innerHTML = daysold;
}
</script>
<hr />
<b>AI摘要</b>
<p id="ai-output">这篇文章介绍了作者如何利用Cloudflare Workers技术为自己的博客添加AI摘要功能替代了之前需要后端支持的AI服务。作者选择了一个基于通义千问的开源项目Qwen-Post-Summary进行改造解决了内容过大和频繁请求的问题通过D1数据库存储文章内容同时通过哈希校验防止内容被篡改。最终作者实现了纯前端的Serverless服务提供实时的AI摘要展示了技术上的DIY乐趣。</p>
<hr />
<ul><li><a href="#起因">起因</a></li><li><a href="#开始制作">开始制作</a></li><li><a href="#使用方法">使用方法</a></li><li><a href="#其他想法">其他想法</a></li><li><a href="#感想">感想</a></li></ul>
<hr />
<main class="post-content e-content" role="main"><p>Cloudflare实在是太强了以至于全都依赖它了😂<!--more--></p>
<h1 id="起因">
<a href="#起因"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 起因
</h1>
<p>虽然很早就在<a href="/2023/04/05/ai.html">关注AI</a>而且也看到有些博客早已用上了AI摘要比如xLog下的但是一般都要后端提前生成好另外那时候还没有那么多免费好用的接口可以用像OpenAI到现在还没有GPT免费的API😂至于花钱就更是想都别想互联网的东西我是不会花钱的就因为这样我一直都没有考虑过给我的博客加AI摘要的功能。 </p><p>
直到前两天看到一个Hexo的博客有一个AI摘要的功能如果是有后端的博客我可能还没什么兴趣但是既然是纯前端的就引发了我的兴趣我大概看了一下用的是一个叫<a href="https://github.com/zhheo/Post-Abstract-AI">Post-Abstract-AI</a>的项目定睛一看居然还是收费的而且API Key还是直接明文放代码里的给我看笑了。如果我拿着这个Key去不停刷使用量不一会就把它刷完了不过这时候我想起来赛博活佛Cloudflare之前也出了AI功能还是免费的我何不用Workers写一个好好打脸一下这个收费的项目就像我对<a href="/2021/02/02/serverchan.html">Server酱</a>做的事情一样。</p>
<h1 id="开始制作">
<a href="#开始制作"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 开始制作
</h1>
<p>首先先不考虑重复造轮子去Github上看看有没有现成的毕竟Cloudflare的这个AI功能也出了不少时间了搜了一下还真有<a href="https://github.com/FloatSheep/Qwen-Post-Summary">Qwen-Post-Summary</a>用的居然还是阿里的通义千问模型这倒是不错毕竟如果用Llama3的话说不定给我生成出来全是英文了国产的模型至少都是对中文优化过的。 </p><p>
我仔细看了看发现它怎么是把文章放GET请求里的要知道浏览器是不会允许超过4KiB的请求头的看了一下代码还截取成前1800字了感觉有点不爽不过我搜了一下为了能简单的做到流式效果用的EventSource功能根本不支持POST请求……看来这个代码不能直接拿来用了另外我也不希望每次打开文章都重新生成摘要那样不仅浪费计算资源而且毫无意义毕竟文章又不会变。所以我首先考虑怎么样存AI生成的结果呢另外为了能通过POST把文章喂给AI我也得考虑存文章。最开始我想着用Workers的KV数据库因为那是最早出的虽然限制很多但当时没得选。但这次点开发现居然有个D1数据库容量更大<a href="https://github.com/bruceharrison1984/kv-d1-benchmark">延迟更低</a>操作次数更多而且还支持SQL语法这不比那个KV数据库好太多了这下都不知道这个KV数据库留着还有啥意义了可能就单纯是为了兼容以前的应用不得不留着了吧。 </p><p>
不过既然会存储内容还得考虑一点就是万一有人偷偷拿我的接口把我的文章内容换了让AI生成了糟糕的内容显示在我的文章里多不合适啊所以为了避免这种问题我每次会对比文章的数字摘要免得有人把我数据库里的文章篡改了🤣。 </p><p>
最终基于上面的代码边查文档边改把代码写出来了,顺便把我之前写的<a href="/2019/06/22/counter.html">博客计数器</a>也一起替换掉了做到真正的Serverless</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">async</span> <span class="kd">function</span> <span class="nx">sha</span><span class="p">(</span><span class="nx">str</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">encoder</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">TextEncoder</span><span class="p">();</span>
<span class="kd">const</span> <span class="nx">data</span> <span class="o">=</span> <span class="nx">encoder</span><span class="p">.</span><span class="nx">encode</span><span class="p">(</span><span class="nx">str</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">hashBuffer</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">crypto</span><span class="p">.</span><span class="nx">subtle</span><span class="p">.</span><span class="nx">digest</span><span class="p">(</span><span class="dl">"</span><span class="s2">SHA-256</span><span class="dl">"</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">hashArray</span> <span class="o">=</span> <span class="nb">Array</span><span class="p">.</span><span class="k">from</span><span class="p">(</span><span class="k">new</span> <span class="nb">Uint8Array</span><span class="p">(</span><span class="nx">hashBuffer</span><span class="p">));</span> <span class="c1">// convert buffer to byte array</span>
<span class="kd">const</span> <span class="nx">hashHex</span> <span class="o">=</span> <span class="nx">hashArray</span>
<span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">b</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">b</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="mi">16</span><span class="p">).</span><span class="nx">padStart</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="dl">"</span><span class="s2">0</span><span class="dl">"</span><span class="p">))</span>
<span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="dl">""</span><span class="p">);</span> <span class="c1">// convert bytes to hex string</span>
<span class="k">return</span> <span class="nx">hashHex</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">async</span> <span class="kd">function</span> <span class="nx">md5</span><span class="p">(</span><span class="nx">str</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">encoder</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">TextEncoder</span><span class="p">();</span>
<span class="kd">const</span> <span class="nx">data</span> <span class="o">=</span> <span class="nx">encoder</span><span class="p">.</span><span class="nx">encode</span><span class="p">(</span><span class="nx">str</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">hashBuffer</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">crypto</span><span class="p">.</span><span class="nx">subtle</span><span class="p">.</span><span class="nx">digest</span><span class="p">(</span><span class="dl">"</span><span class="s2">MD5</span><span class="dl">"</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">hashArray</span> <span class="o">=</span> <span class="nb">Array</span><span class="p">.</span><span class="k">from</span><span class="p">(</span><span class="k">new</span> <span class="nb">Uint8Array</span><span class="p">(</span><span class="nx">hashBuffer</span><span class="p">));</span> <span class="c1">// convert buffer to byte array</span>
<span class="kd">const</span> <span class="nx">hashHex</span> <span class="o">=</span> <span class="nx">hashArray</span>
<span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">b</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">b</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="mi">16</span><span class="p">).</span><span class="nx">padStart</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="dl">"</span><span class="s2">0</span><span class="dl">"</span><span class="p">))</span>
<span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="dl">""</span><span class="p">);</span> <span class="c1">// convert bytes to hex string</span>
<span class="k">return</span> <span class="nx">hashHex</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">export</span> <span class="k">default</span> <span class="p">{</span>
<span class="k">async</span> <span class="nx">fetch</span><span class="p">(</span><span class="nx">request</span><span class="p">,</span> <span class="nx">env</span><span class="p">,</span> <span class="nx">ctx</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">db</span> <span class="o">=</span> <span class="nx">env</span><span class="p">.</span><span class="nx">blog_summary</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">url</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">URL</span><span class="p">(</span><span class="nx">request</span><span class="p">.</span><span class="nx">url</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">query</span> <span class="o">=</span> <span class="nb">decodeURIComponent</span><span class="p">(</span><span class="nx">url</span><span class="p">.</span><span class="nx">searchParams</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">id</span><span class="dl">'</span><span class="p">));</span>
<span class="kd">const</span> <span class="nx">commonHeader</span> <span class="o">=</span> <span class="p">{</span>
<span class="dl">'</span><span class="s1">Access-Control-Allow-Origin</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">*</span><span class="dl">'</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">Access-Control-Allow-Methods</span><span class="dl">'</span><span class="p">:</span> <span class="dl">"</span><span class="s2">*</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">Access-Control-Allow-Headers</span><span class="dl">'</span><span class="p">:</span> <span class="dl">"</span><span class="s2">*</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">Access-Control-Max-Age</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">86400</span><span class="dl">'</span><span class="p">,</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">query</span> <span class="o">==</span> <span class="dl">"</span><span class="s2">null</span><span class="dl">"</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Response</span><span class="p">(</span><span class="dl">"</span><span class="s2">id cannot be none</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span>
<span class="na">headers</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">'</span><span class="s1">Access-Control-Allow-Origin</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">*</span><span class="dl">'</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">Access-Control-Allow-Methods</span><span class="dl">'</span><span class="p">:</span> <span class="dl">"</span><span class="s2">*</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">Access-Control-Allow-Headers</span><span class="dl">'</span><span class="p">:</span> <span class="dl">"</span><span class="s2">*</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">Access-Control-Max-Age</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">86400</span><span class="dl">'</span><span class="p">,</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">url</span><span class="p">.</span><span class="nx">pathname</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="dl">"</span><span class="s2">/summary</span><span class="dl">"</span><span class="p">))</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">result</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">db</span><span class="p">.</span><span class="nx">prepare</span><span class="p">(</span>
<span class="dl">"</span><span class="s2">SELECT content FROM blog_summary WHERE id = ?1</span><span class="dl">"</span>
<span class="p">).</span><span class="nx">bind</span><span class="p">(</span><span class="nx">query</span><span class="p">).</span><span class="nx">first</span><span class="p">(</span><span class="dl">"</span><span class="s2">content</span><span class="dl">"</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">result</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Response</span><span class="p">(</span><span class="dl">"</span><span class="s2">No Record</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span>
<span class="na">headers</span><span class="p">:</span> <span class="nx">commonHeader</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">messages</span> <span class="o">=</span> <span class="p">[</span>
<span class="p">{</span>
<span class="na">role</span><span class="p">:</span> <span class="dl">"</span><span class="s2">system</span><span class="dl">"</span><span class="p">,</span> <span class="na">content</span><span class="p">:</span> <span class="s2">`
你是一个专业的文章摘要助手。你的主要任务是对各种文章进行精炼和摘要,帮助用户快速了解文章的核心内容。你读完整篇文章后,能够提炼出文章的关键信息,以及作者的主要观点和结论。
技能
精炼摘要:能够快速阅读并理解文章内容,提取出文章的主要关键点,用简洁明了的中文进行阐述。
关键信息提取:识别文章中的重要信息,如主要观点、数据支持、结论等,并有效地进行总结。
客观中立:在摘要过程中保持客观中立的态度,避免引入个人偏见。
约束
输出内容必须以中文进行。
必须确保摘要内容准确反映原文章的主旨和重点。
尊重原文的观点,不能进行歪曲或误导。
在摘要中明确区分事实与作者的意见或分析。
提示
不需要在回答中注明摘要(不需要使用冒号),只需要输出内容。
格式
你的回答格式应该如下:
这篇文章介绍了&lt;这里是内容&gt;
`</span> <span class="p">},</span>
<span class="p">{</span> <span class="na">role</span><span class="p">:</span> <span class="dl">"</span><span class="s2">user</span><span class="dl">"</span><span class="p">,</span> <span class="na">content</span><span class="p">:</span> <span class="nx">result</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">5000</span><span class="p">)</span> <span class="p">}</span>
<span class="p">]</span>
<span class="kd">const</span> <span class="nx">stream</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">env</span><span class="p">.</span><span class="nx">AI</span><span class="p">.</span><span class="nx">run</span><span class="p">(</span><span class="dl">'</span><span class="s1">@cf/qwen/qwen1.5-14b-chat-awq</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
<span class="nx">messages</span><span class="p">,</span>
<span class="na">stream</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="p">});</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Response</span><span class="p">(</span><span class="nx">stream</span><span class="p">,</span> <span class="p">{</span>
<span class="na">headers</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">"</span><span class="s2">content-type</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">text/event-stream; charset=utf-8</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">Access-Control-Allow-Origin</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">*</span><span class="dl">'</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">Access-Control-Allow-Methods</span><span class="dl">'</span><span class="p">:</span> <span class="dl">"</span><span class="s2">*</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">Access-Control-Allow-Headers</span><span class="dl">'</span><span class="p">:</span> <span class="dl">"</span><span class="s2">*</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">Access-Control-Max-Age</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">86400</span><span class="dl">'</span><span class="p">,</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">url</span><span class="p">.</span><span class="nx">pathname</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="dl">"</span><span class="s2">/get_summary</span><span class="dl">"</span><span class="p">))</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">orig_sha</span> <span class="o">=</span> <span class="nb">decodeURIComponent</span><span class="p">(</span><span class="nx">url</span><span class="p">.</span><span class="nx">searchParams</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">sign</span><span class="dl">'</span><span class="p">));</span>
<span class="kd">let</span> <span class="nx">result</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">db</span><span class="p">.</span><span class="nx">prepare</span><span class="p">(</span>
<span class="dl">"</span><span class="s2">SELECT content FROM blog_summary WHERE id = ?1</span><span class="dl">"</span>
<span class="p">).</span><span class="nx">bind</span><span class="p">(</span><span class="nx">query</span><span class="p">).</span><span class="nx">first</span><span class="p">(</span><span class="dl">"</span><span class="s2">content</span><span class="dl">"</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">result</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Response</span><span class="p">(</span><span class="dl">"</span><span class="s2">no</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span>
<span class="na">headers</span><span class="p">:</span> <span class="nx">commonHeader</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="kd">let</span> <span class="nx">result_sha</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">sha</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">result_sha</span> <span class="o">!=</span> <span class="nx">orig_sha</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Response</span><span class="p">(</span><span class="dl">"</span><span class="s2">no</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span>
<span class="na">headers</span><span class="p">:</span> <span class="nx">commonHeader</span>
<span class="p">});</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">resp</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">db</span><span class="p">.</span><span class="nx">prepare</span><span class="p">(</span>
<span class="dl">"</span><span class="s2">SELECT summary FROM blog_summary WHERE id = ?1</span><span class="dl">"</span>
<span class="p">).</span><span class="nx">bind</span><span class="p">(</span><span class="nx">query</span><span class="p">).</span><span class="nx">first</span><span class="p">(</span><span class="dl">"</span><span class="s2">summary</span><span class="dl">"</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">resp</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Response</span><span class="p">(</span><span class="nx">resp</span><span class="p">,</span> <span class="p">{</span>
<span class="na">headers</span><span class="p">:</span> <span class="nx">commonHeader</span>
<span class="p">});</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">messages</span> <span class="o">=</span> <span class="p">[</span>
<span class="p">{</span>
<span class="na">role</span><span class="p">:</span> <span class="dl">"</span><span class="s2">system</span><span class="dl">"</span><span class="p">,</span> <span class="na">content</span><span class="p">:</span> <span class="s2">`
你是一个专业的文章摘要助手。你的主要任务是对各种文章进行精炼和摘要,帮助用户快速了解文章的核心内容。你读完整篇文章后,能够提炼出文章的关键信息,以及作者的主要观点和结论。
技能
精炼摘要:能够快速阅读并理解文章内容,提取出文章的主要关键点,用简洁明了的中文进行阐述。
关键信息提取:识别文章中的重要信息,如主要观点、数据支持、结论等,并有效地进行总结。
客观中立:在摘要过程中保持客观中立的态度,避免引入个人偏见。
约束
输出内容必须以中文进行。
必须确保摘要内容准确反映原文章的主旨和重点。
尊重原文的观点,不能进行歪曲或误导。
在摘要中明确区分事实与作者的意见或分析。
提示
不需要在回答中注明摘要(不需要使用冒号),只需要输出内容。
格式
你的回答格式应该如下:
这篇文章介绍了&lt;这里是内容&gt;
`</span> <span class="p">},</span>
<span class="p">{</span> <span class="na">role</span><span class="p">:</span> <span class="dl">"</span><span class="s2">user</span><span class="dl">"</span><span class="p">,</span> <span class="na">content</span><span class="p">:</span> <span class="nx">result</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">5000</span><span class="p">)</span> <span class="p">}</span>
<span class="p">]</span>
<span class="kd">const</span> <span class="nx">answer</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">env</span><span class="p">.</span><span class="nx">AI</span><span class="p">.</span><span class="nx">run</span><span class="p">(</span><span class="dl">'</span><span class="s1">@cf/qwen/qwen1.5-14b-chat-awq</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
<span class="nx">messages</span><span class="p">,</span>
<span class="na">stream</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="p">});</span>
<span class="nx">resp</span> <span class="o">=</span> <span class="nx">answer</span><span class="p">.</span><span class="nx">response</span>
<span class="k">await</span> <span class="nx">db</span><span class="p">.</span><span class="nx">prepare</span><span class="p">(</span><span class="dl">"</span><span class="s2">UPDATE blog_summary SET summary = ?1 WHERE id = ?2</span><span class="dl">"</span><span class="p">)</span>
<span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="nx">resp</span><span class="p">,</span> <span class="nx">query</span><span class="p">).</span><span class="nx">run</span><span class="p">();</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Response</span><span class="p">(</span><span class="nx">resp</span><span class="p">,</span> <span class="p">{</span>
<span class="na">headers</span><span class="p">:</span> <span class="nx">commonHeader</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">url</span><span class="p">.</span><span class="nx">pathname</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="dl">"</span><span class="s2">/is_uploaded</span><span class="dl">"</span><span class="p">))</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">orig_sha</span> <span class="o">=</span> <span class="nb">decodeURIComponent</span><span class="p">(</span><span class="nx">url</span><span class="p">.</span><span class="nx">searchParams</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">sign</span><span class="dl">'</span><span class="p">));</span>
<span class="kd">let</span> <span class="nx">result</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">db</span><span class="p">.</span><span class="nx">prepare</span><span class="p">(</span>
<span class="dl">"</span><span class="s2">SELECT content FROM blog_summary WHERE id = ?1</span><span class="dl">"</span>
<span class="p">).</span><span class="nx">bind</span><span class="p">(</span><span class="nx">query</span><span class="p">).</span><span class="nx">first</span><span class="p">(</span><span class="dl">"</span><span class="s2">content</span><span class="dl">"</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">result</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Response</span><span class="p">(</span><span class="dl">"</span><span class="s2">no</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span>
<span class="na">headers</span><span class="p">:</span> <span class="nx">commonHeader</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="kd">let</span> <span class="nx">result_sha</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">sha</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">result_sha</span> <span class="o">!=</span> <span class="nx">orig_sha</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Response</span><span class="p">(</span><span class="dl">"</span><span class="s2">no</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span>
<span class="na">headers</span><span class="p">:</span> <span class="nx">commonHeader</span>
<span class="p">});</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Response</span><span class="p">(</span><span class="dl">"</span><span class="s2">yes</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span>
<span class="na">headers</span><span class="p">:</span> <span class="nx">commonHeader</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">url</span><span class="p">.</span><span class="nx">pathname</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="dl">"</span><span class="s2">/upload_blog</span><span class="dl">"</span><span class="p">))</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">request</span><span class="p">.</span><span class="nx">method</span> <span class="o">==</span> <span class="dl">"</span><span class="s2">POST</span><span class="dl">"</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">data</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">request</span><span class="p">.</span><span class="nx">text</span><span class="p">();</span>
<span class="kd">let</span> <span class="nx">result</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">db</span><span class="p">.</span><span class="nx">prepare</span><span class="p">(</span>
<span class="dl">"</span><span class="s2">SELECT content FROM blog_summary WHERE id = ?1</span><span class="dl">"</span>
<span class="p">).</span><span class="nx">bind</span><span class="p">(</span><span class="nx">query</span><span class="p">).</span><span class="nx">first</span><span class="p">(</span><span class="dl">"</span><span class="s2">content</span><span class="dl">"</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">result</span><span class="p">)</span> <span class="p">{</span>
<span class="k">await</span> <span class="nx">db</span><span class="p">.</span><span class="nx">prepare</span><span class="p">(</span><span class="dl">"</span><span class="s2">INSERT INTO blog_summary(id, content) VALUES (?1, ?2)</span><span class="dl">"</span><span class="p">)</span>
<span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="nx">query</span><span class="p">,</span> <span class="nx">data</span><span class="p">).</span><span class="nx">run</span><span class="p">();</span>
<span class="nx">result</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">db</span><span class="p">.</span><span class="nx">prepare</span><span class="p">(</span>
<span class="dl">"</span><span class="s2">SELECT content FROM blog_summary WHERE id = ?1</span><span class="dl">"</span>
<span class="p">).</span><span class="nx">bind</span><span class="p">(</span><span class="nx">query</span><span class="p">).</span><span class="nx">first</span><span class="p">(</span><span class="dl">"</span><span class="s2">content</span><span class="dl">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">result</span> <span class="o">!=</span> <span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="k">await</span> <span class="nx">db</span><span class="p">.</span><span class="nx">prepare</span><span class="p">(</span><span class="dl">"</span><span class="s2">UPDATE blog_summary SET content = ?1, summary = NULL WHERE id = ?2</span><span class="dl">"</span><span class="p">)</span>
<span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="nx">data</span><span class="p">,</span> <span class="nx">query</span><span class="p">).</span><span class="nx">run</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Response</span><span class="p">(</span><span class="dl">"</span><span class="s2">OK</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span>
<span class="na">headers</span><span class="p">:</span> <span class="nx">commonHeader</span>
<span class="p">});</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Response</span><span class="p">(</span><span class="dl">"</span><span class="s2">need post</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span>
<span class="na">headers</span><span class="p">:</span> <span class="nx">commonHeader</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">url</span><span class="p">.</span><span class="nx">pathname</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="dl">"</span><span class="s2">/count_click</span><span class="dl">"</span><span class="p">))</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">id_md5</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">md5</span><span class="p">(</span><span class="nx">query</span><span class="p">);</span>
<span class="kd">let</span> <span class="nx">count</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">db</span><span class="p">.</span><span class="nx">prepare</span><span class="p">(</span><span class="dl">"</span><span class="s2">SELECT `counter` FROM `counter` WHERE `url` = ?1</span><span class="dl">"</span><span class="p">)</span>
<span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="nx">id_md5</span><span class="p">).</span><span class="nx">first</span><span class="p">(</span><span class="dl">"</span><span class="s2">counter</span><span class="dl">"</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">url</span><span class="p">.</span><span class="nx">pathname</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="dl">"</span><span class="s2">/count_click_add</span><span class="dl">"</span><span class="p">))</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">count</span><span class="p">)</span> <span class="p">{</span>
<span class="k">await</span> <span class="nx">db</span><span class="p">.</span><span class="nx">prepare</span><span class="p">(</span><span class="dl">"</span><span class="s2">INSERT INTO `counter` (`url`, `counter`) VALUES (?1, 1)</span><span class="dl">"</span><span class="p">)</span>
<span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="nx">id_md5</span><span class="p">).</span><span class="nx">run</span><span class="p">();</span>
<span class="nx">count</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">count</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">await</span> <span class="nx">db</span><span class="p">.</span><span class="nx">prepare</span><span class="p">(</span><span class="dl">"</span><span class="s2">UPDATE `counter` SET `counter` = ?1 WHERE `url` = ?2</span><span class="dl">"</span><span class="p">)</span>
<span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="nx">count</span><span class="p">,</span> <span class="nx">id_md5</span><span class="p">).</span><span class="nx">run</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">count</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Response</span><span class="p">(</span><span class="nx">count</span><span class="p">,</span> <span class="p">{</span>
<span class="na">headers</span><span class="p">:</span> <span class="nx">commonHeader</span>
<span class="p">});</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">Response</span><span class="p">.</span><span class="nx">redirect</span><span class="p">(</span><span class="dl">"</span><span class="s2">https://mabbs.github.io</span><span class="dl">"</span><span class="p">,</span> <span class="mi">302</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>另外也写了配套的前端代码用的jQuery其实应该用Fetch的😂</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;b&gt;</span>AI摘要<span class="nt">&lt;/b&gt;</span>
<span class="nt">&lt;p</span> <span class="na">id=</span><span class="s">"ai-output"</span><span class="nt">&gt;</span>正在生成中……<span class="nt">&lt;/p&gt;</span>
<span class="nt">&lt;script&gt;</span>
<span class="k">async</span> <span class="kd">function</span> <span class="nx">sha</span><span class="p">(</span><span class="nx">str</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">encoder</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">TextEncoder</span><span class="p">();</span>
<span class="kd">const</span> <span class="nx">data</span> <span class="o">=</span> <span class="nx">encoder</span><span class="p">.</span><span class="nx">encode</span><span class="p">(</span><span class="nx">str</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">hashBuffer</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">crypto</span><span class="p">.</span><span class="nx">subtle</span><span class="p">.</span><span class="nx">digest</span><span class="p">(</span><span class="dl">"</span><span class="s2">SHA-256</span><span class="dl">"</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">hashArray</span> <span class="o">=</span> <span class="nb">Array</span><span class="p">.</span><span class="k">from</span><span class="p">(</span><span class="k">new</span> <span class="nb">Uint8Array</span><span class="p">(</span><span class="nx">hashBuffer</span><span class="p">));</span> <span class="c1">// convert buffer to byte array</span>
<span class="kd">const</span> <span class="nx">hashHex</span> <span class="o">=</span> <span class="nx">hashArray</span>
<span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">b</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">b</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="mi">16</span><span class="p">).</span><span class="nx">padStart</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="dl">"</span><span class="s2">0</span><span class="dl">"</span><span class="p">))</span>
<span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="dl">""</span><span class="p">);</span> <span class="c1">// convert bytes to hex string</span>
<span class="k">return</span> <span class="nx">hashHex</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">async</span> <span class="kd">function</span> <span class="nx">ai_gen</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">postContent</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">文章标题:</span><span class="dl">"</span> <span class="o">+</span> <span class="p">{{</span> <span class="nx">page</span><span class="p">.</span><span class="nx">title</span> <span class="o">|</span> <span class="nx">jsonify</span> <span class="p">}}</span> <span class="o">+</span> <span class="dl">"</span><span class="s2">;文章内容:</span><span class="dl">"</span> <span class="o">+</span> <span class="p">{{</span> <span class="nx">page</span><span class="p">.</span><span class="nx">content</span> <span class="o">|</span> <span class="nx">strip_html</span> <span class="o">|</span> <span class="nx">strip_newlines</span> <span class="o">|</span> <span class="nx">jsonify</span> <span class="p">}};</span>
<span class="kd">var</span> <span class="nx">postContentSign</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">sha</span><span class="p">(</span><span class="nx">postContent</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">outputContainer</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">ai-output</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">$</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">"</span><span class="s2">https://summary.mayx.eu.org/is_uploaded?id={{ page.url }}&amp;sign=</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">postContentSign</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">data</span> <span class="o">==</span> <span class="dl">"</span><span class="s2">yes</span><span class="dl">"</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">$</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">"</span><span class="s2">https://summary.mayx.eu.org/get_summary?id={{ page.url }}&amp;sign=</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">postContentSign</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">data2</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">outputContainer</span><span class="p">.</span><span class="nx">textContent</span> <span class="o">=</span> <span class="nx">data2</span><span class="p">;</span>
<span class="p">});</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">$</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">"</span><span class="s2">https://summary.mayx.eu.org/upload_blog?id={{ page.url }}</span><span class="dl">"</span><span class="p">,</span> <span class="nx">postContent</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">$</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">"</span><span class="s2">https://summary.mayx.eu.org/get_summary?id={{ page.url }}&amp;sign=</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">postContentSign</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">evSource</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">EventSource</span><span class="p">(</span><span class="dl">"</span><span class="s2">https://summary.mayx.eu.org/summary?id={{ page.url }}</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">outputContainer</span><span class="p">.</span><span class="nx">textContent</span> <span class="o">=</span> <span class="dl">""</span><span class="p">;</span>
<span class="nx">evSource</span><span class="p">.</span><span class="nx">onmessage</span> <span class="o">=</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">data</span> <span class="o">==</span> <span class="dl">"</span><span class="s2">[DONE]</span><span class="dl">"</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">evSource</span><span class="p">.</span><span class="nx">close</span><span class="p">();</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">data</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
<span class="nx">outputContainer</span><span class="p">.</span><span class="nx">textContent</span> <span class="o">+=</span> <span class="nx">data</span><span class="p">.</span><span class="nx">response</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="nx">ai_gen</span><span class="p">();</span>
<span class="nt">&lt;/script&gt;</span>
</code></pre></div></div>
<p>本来文章内容应该从html里读更好一些但是标签啥的还得用正则去掉感觉不如Liquid方便😂。另外博客计数器不应该用MD5的但懒得改之前的数据了还好Cloudflare Workers为了兼容是支持MD5的免得我还得想办法改数据库里的数据。</p>
<h1 id="使用方法">
<a href="#使用方法"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 使用方法
</h1>
<p>如果想给自己的静态博客加AI摘要功能的话也可以用我的接口把前端代码粘到模板里就行反正是用的Cloudflare的资源而且现在通义千问的模型还是Beta版调用没有次数限制就算之后变正式版也能每天免费用1w个神经元好像可以进行1k次左右的生成完全够用了只要别和我文章url重了就行。 </p><p>
不过毕竟Workers本身是有每日调用次数限制的自己部署当然更好。方法也很简单首先在D1里创建一个数据库然后创建一个Workers在变量里绑定AI和新建的D1数据库名字要起成blog_summary如果想换名字就要改代码里面建一张叫做blog_summary的表需要有3个字段分别是id、content、summary都是text类型如果想用博客计数器功能就再加一张counter表一个是urltext类型另一个是counterint类型。本来博客计数器接口名字也打算用counter的结果不知道AdBlock有什么大病居然会屏蔽“counter?id=”这样的请求😆害的我只能改成count_click这样的名字了。</p>
<h1 id="其他想法">
<a href="#其他想法"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 其他想法
</h1>
<p>加了这个功能之后感觉效果还挺不错的,这下就有点想加点别的功能了,比如文章推荐和知识库问答啥的, <del>不过这个似乎需要什么向量数据库,而且数据需要进行“嵌入”处理,这用现有的东西感觉难度实在是太高了所以就算了……</del> 在2024.09.27中<a href="/2024/09/27/rag.html">已经实现了</a> 另外还想用文生图模型给我的文章加个头图,不过我天天写的都是些技术文章,没啥图可加吧🤣。其他的之后再看看有什么有意思的功能再加吧。</p>
<h1 id="感想">
<a href="#感想"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 感想
</h1>
<p>Cloudflare真不愧是赛博活佛这波操作下来不就省下了那笔生成费用啥都是免费的不过问题就是Cloudflare在这方面几乎是垄断地位虽然国际大厂倒是不担心倒闭不过万一挂了想再找个这样厉害的平台可就没了😆。</p></main>
<small style="display: block">tags: <a rel="category tag" class="p-category" href="/search.html?keyword=Cloudflare"><em>Cloudflare</em></a> - <a rel="category tag" class="p-category" href="/search.html?keyword=Workers"><em>Workers</em></a> - <a rel="category tag" class="p-category" href="/search.html?keyword=AI"><em>AI</em></a> - <a rel="category tag" class="p-category" href="/search.html?keyword=%E5%8D%9A%E5%AE%A2"><em>博客</em></a> <span style="float: right;"><a href="https://gitlab.com/mayx/mayx.gitlab.io/tree/master/_posts/2024-07-03-ai-summary.md">查看原始文件</a></span></small>
<h4 style="border-bottom: 1px solid #e5e5e5;margin: 2em 0 5px;">推荐文章</h4>
<p id="suggest-container">Loading...</p>
<script>
var suggest = $("#suggest-container");
$.get(BlogAPI + "/suggest?id=/2024/07/03/ai-summary.html&update=" + lastUpdated.valueOf(), function (data) {
if (data.length) {
getSearchJSON(function (search) {
suggest.empty();
var searchMap = {};
for (var i = 0; i < search.length; i++) {
searchMap[search[i].url] = search[i];
}
var tooltip = $('<div class="content-tooltip"></div>').appendTo('body').hide();
for (var j = 0; j < data.length; j++) {
var item = searchMap[data[j].id];
if (item) {
var link = $('<a href="' + item.url + '">' + item.title + '</a>');
var contentPreview = item.content.substring(0, 100);
if (item.content.length > 100) {
contentPreview += "……";
}
link.hover(
function(e) {
tooltip.text($(this).data('content'))
.css({
top: e.pageY + 10,
left: e.pageX + 10
})
.show();
},
function() {
tooltip.hide();
}
).mousemove(function(e) {
tooltip.css({
top: e.pageY + 10,
left: e.pageX + 10
});
}).data('content', contentPreview);
suggest.append(link);
suggest.append(' - ' + item.date + '<br />');
}
}
});
} else {
suggest.html("暂无推荐文章……");
}
});
</script>
<br />
<div class="pagination">
<span class="prev">
<a href="/2024/06/16/hackintosh.html">
上一篇Hackintosh使用体验
</a>
</span>
<br />
<span class="next">
<a href="/2024/08/03/cangjie.html">
下一篇:华为仓颉语言使用体验
</a>
</span>
</div>
<!--[if !IE]> -->
<link rel="stylesheet" href="/assets/css/gitalk.css">
<script src="/assets/js/gitalk.min.js"></script>
<div id="gitalk-container"></div>
<script>
var gitalk = new Gitalk({
clientID: '36557aec4c3cb04f7ac6',
clientSecret: 'ac32993299751cb5a9ba81cf2b171cca65879cdb',
repo: 'mabbs.github.io',
owner: 'Mabbs',
admin: ['Mabbs'],
id: '/2024/07/03/ai-summary', // Ensure uniqueness and length less than 50
distractionFreeMode: false, // Facebook-like distraction free mode
proxy: "https://cors-anywhere.mayx.eu.org/?https://github.com/login/oauth/access_token"
})
gitalk.render('gitalk-container')
</script>
<!-- <![endif]-->
</section>
<!--[if !IE]> -->
<div id="landlord" style="left:5px;bottom:0px;">
<div class="message" style="opacity:0"></div>
<canvas id="live2d" width="500" height="560" class="live2d"></canvas>
<div class="live_talk_input_body">
<form id="live_talk_input_form">
<div class="live_talk_input_name_body" >
<input type="checkbox" id="load_this" />
<input type="hidden" id="post_id" value="/2024/07/03/ai-summary.html" />
<label for="load_this">
<span style="font-size: 11px; color: #fff;">&#160;想问这篇文章</span>
</label>
</div>
<div class="live_talk_input_text_body">
<input name="talk" type="text" class="live_talk_talk white_input" id="AIuserText" autocomplete="off" placeholder="要和我聊什么呀?" />
<button type="submit" class="live_talk_send_btn" id="talk_send">发送</button>
</div>
</form>
</div>
<input name="live_talk" id="live_talk" value="1" type="hidden" />
<div class="live_ico_box" style="display:none;">
<div class="live_ico_item type_info" id="showInfoBtn"></div>
<div class="live_ico_item type_talk" id="showTalkBtn"></div>
<div class="live_ico_item type_music" id="musicButton"></div>
<div class="live_ico_item type_youdu" id="youduButton"></div>
<div class="live_ico_item type_quit" id="hideButton"></div>
<input name="live_statu_val" id="live_statu_val" value="0" type="hidden" />
<audio src="" style="display:none;" id="live2d_bgm" data-bgm="0" preload="none"></audio>
<input id="duType" value="douqilai" type="hidden" />
</div>
</div>
<div id="open_live2d">召唤伊斯特瓦尔</div>
<!-- <![endif]-->
<footer>
<p>
<small>Made with ❤ by Mayx<br />Last updated at 2026-01-01 00:00:18<br /> 总字数614622 - 文章数178 - <a href="/atom.xml" >Atom</a> - <a href="/README.html" >About</a></small>
</p>
</footer>
</div>
<script src="/assets/js/scale.fix.js"></script>
<!--[if !IE]> -->
<script src="/assets/js/main_new.js"></script>
<script src="/Live2dHistoire/live2d/js/live2d.js"></script>
<script src="/Live2dHistoire/live2d/js/message.js"></script>
<!-- <![endif]-->
</body>
</html>