mirror of
https://codeberg.org/mayx/pages
synced 2026-01-02 02:03:40 +08:00
update
This commit is contained in:
591
2024/07/03/ai-summary.html
Normal file
591
2024/07/03/ai-summary.html
Normal file
@@ -0,0 +1,591 @@
|
||||
<!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.." /> <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">=></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">=></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">`
|
||||
你是一个专业的文章摘要助手。你的主要任务是对各种文章进行精炼和摘要,帮助用户快速了解文章的核心内容。你读完整篇文章后,能够提炼出文章的关键信息,以及作者的主要观点和结论。
|
||||
技能
|
||||
精炼摘要:能够快速阅读并理解文章内容,提取出文章的主要关键点,用简洁明了的中文进行阐述。
|
||||
关键信息提取:识别文章中的重要信息,如主要观点、数据支持、结论等,并有效地进行总结。
|
||||
客观中立:在摘要过程中保持客观中立的态度,避免引入个人偏见。
|
||||
约束
|
||||
输出内容必须以中文进行。
|
||||
必须确保摘要内容准确反映原文章的主旨和重点。
|
||||
尊重原文的观点,不能进行歪曲或误导。
|
||||
在摘要中明确区分事实与作者的意见或分析。
|
||||
提示
|
||||
不需要在回答中注明摘要(不需要使用冒号),只需要输出内容。
|
||||
格式
|
||||
你的回答格式应该如下:
|
||||
这篇文章介绍了<这里是内容>
|
||||
`</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">`
|
||||
你是一个专业的文章摘要助手。你的主要任务是对各种文章进行精炼和摘要,帮助用户快速了解文章的核心内容。你读完整篇文章后,能够提炼出文章的关键信息,以及作者的主要观点和结论。
|
||||
技能
|
||||
精炼摘要:能够快速阅读并理解文章内容,提取出文章的主要关键点,用简洁明了的中文进行阐述。
|
||||
关键信息提取:识别文章中的重要信息,如主要观点、数据支持、结论等,并有效地进行总结。
|
||||
客观中立:在摘要过程中保持客观中立的态度,避免引入个人偏见。
|
||||
约束
|
||||
输出内容必须以中文进行。
|
||||
必须确保摘要内容准确反映原文章的主旨和重点。
|
||||
尊重原文的观点,不能进行歪曲或误导。
|
||||
在摘要中明确区分事实与作者的意见或分析。
|
||||
提示
|
||||
不需要在回答中注明摘要(不需要使用冒号),只需要输出内容。
|
||||
格式
|
||||
你的回答格式应该如下:
|
||||
这篇文章介绍了<这里是内容>
|
||||
`</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"><b></span>AI摘要<span class="nt"></b></span>
|
||||
<span class="nt"><p</span> <span class="na">id=</span><span class="s">"ai-output"</span><span class="nt">></span>正在生成中……<span class="nt"></p></span>
|
||||
<span class="nt"><script></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">=></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 }}&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 }}&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 }}&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">=></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"></script></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表,一个是url,text类型,另一个是counter,int类型。本来博客计数器接口名字也打算用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;"> 想问这篇文章</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>
|
||||
Reference in New Issue
Block a user