V2EX 评论区总结
当前为
// ==UserScript==
// @name V2EX-Comments-Summarizer
// @namespace https://github.com/banbri
// @version 1.0
// @description V2EX 评论区总结
// @author Banbri
// @match https://www.v2ex.com/t/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=v2ex.com
// @license GPL-2.0-only
// ==/UserScript==
const rightbar = document.getElementById('Rightbar')
const box = document.createElement('div')
box.className = 'box'
box.style.minHeight = '200px'
box.style.padding = '10px'
box.style.overflowX = 'hidden'
rightbar.appendChild(box)
// 向 box 中添加一个 title 为 '评论区总结',并且添加样式
const title = document.createElement('div')
title.innerText = '评论区总结:'
title.style.textAlign = 'left'
title.style.fontWeight = 'bold'
box.appendChild(title)
// 再新建一个 div,用于存放评论区总结的内容
const contentDiv = document.createElement('div')
contentDiv.className = 'reply_content'
contentDiv.style.textAlign = 'left'
box.appendChild(contentDiv)
// 获取到所有的评论
const comments = document.querySelectorAll('.reply_content')
let contentText = 'Generating...'
for (let i = 0; i < comments.length; i++) {
contentText += comments[i].innerText
}
// 如果评论内容低于 200 个字符,就不进行总结
if (contentText.length < 200) {
contentDiv.innerText = '评论内容太少,不进行总结。'
} else {
if (contentText.length > 2000) {
contentText = contentText.substring(0, 2000)
}
getSummary()
}
async function getSummary() {
const param = {
model: 'gpt-3.5-turbo',
temperature: 1,
top_p: 0.9,
frequency_penalty: 0,
presence_penalty: 0,
stop: '',
messages: [
{ role: 'assistant', content: contentText },
{
role: 'user',
content: '这是一个帖子的评论区,请总结一下,仅回复总结内容。',
},
],
stream: true,
}
const response = await fetch('https://thread-sum.com/v1/chat/completions', {
method: 'POST',
body: JSON.stringify(param),
})
const reader = response.body.getReader()
const decoder = new TextDecoder('utf-8')
contentText.innerText = ''
let text = ''
while (true) {
const { done, value } = await reader.read()
if (done) {
break
}
// Massage and parse the chunk of data
const chunk = decoder.decode(value, { stream: true })
const dataStrList = chunk.split('\n\n')
// eslint-disable-next-line
dataStrList.forEach((dataStr) => {
const dataJson = dataStr.replace(/^data:/, '').trim()
try {
const data = JSON.parse(dataJson)
const content = data?.choices[0]?.delta?.content
if (!content) return
text += content
contentDiv.innerText = text
} catch (e) {}
})
}
}