LLM 正在成為現代開發工具和 AI 代理的支柱。它已經可以產生程式碼。但問題是:輸出是靜態的。

你仍然需要複製程式碼,貼上到專案中,啟動開發伺服器,修復建置問題,並手動連接邏輯或狀態。這些工作如果擴展到幾十個 UI 元件,很快就會變得混亂不堪。

Thesys React SDK 讓您跳過這一步。您可以即時將 LLM 答案轉換為即時渲染的互動式 UI。

今天,我們將了解「生成式 UI」的真正意義,Thesys 如何將 LLM 與前端層連接起來,以及如何使用 C1 API 和 React SDK 將其與您的 AI 堆疊整合。

讓我們開始吧。

系統


涵蓋哪些內容?

總之,我們將詳細介紹這些主題。

1)什麼是生成式UI?

2)Thesys 的工作原理:C1 API 和 GenUI React SDK

3) 使用 Thesys 建立生成式 UI 的逐步指南。

4) 所有主要的 AI 堆疊都可以與 Thesys 一起使用。

如果您有興趣自己探索,請查看thesys.dev

{% 嵌入 https://www.youtube.com/watch?v=oyAKkW9q1Mg

%}


1.什麼是生成式UI?

如果您最近使用過 Slack、Gmail 或任何儀表板工具等應用程式,您會注意到一件事: they all look insanely similar

傳統的 UI 是靜態的。無論使用者是誰、出於什麼原因,每個使用者看到的都是相同的佈局。而生成式 UI 變化則允許介面根據每個使用者進行動態組合。

但並非所有基於提示的 UI 系統都是一樣的。它們的差異如下:

  • Prompt to design :將 LLM 與電腦視覺模型(如擴散或 GAN)結合,用於佈局生成。它通常嵌入在 Figma 等設計工具中。

  • Prompt to UI :使用 LLM(如 GPT-4、Claude)來理解提示並產生生產級前端/後端程式碼。

  • Generative UI :需要可自訂的 UI 庫、用於儲存使用者上下文的內存,以及一個能夠持續重塑 UI 的即時 GenUI 引擎。 Thesys 就屬於此類。

如果您有興趣了解更多有關幕後發生的事情,請查看生成 UI、提示 UI 和提示設計

生成式使用者介面

讓我們簡單了解一下生成式 UI 的工作原理(概念上):

✅ 1. 系統了解你的上下文

在生成式 UI 系統中,佈局並非硬編碼。它會根據使用者身分、操作方式以及與應用程式的互動方式而改變。系統會收集以下上下文資訊:

  • 你過去的行為

  • 您的偏好(例如黑暗模式)

  • 設備類型、螢幕尺寸、位置

  • 甚至一天中的時間或可存取性設置

例子?

假設您正在使用一款共乘應用程式。該應用程式會偵測運動和位置訊號,辨識您正在駕駛,並立即切換到語音優先的使用者介面。

大按鈕、最少的干擾和語音提示可引導您完成拾取和導航等操作。

這不僅僅是響應式設計。

這是一個understands your context and adapts itself以適應情況的使用者介面。

✅ 2. AI 使用現有的 UI 元素庫並且不會產生幻覺。

現在,人工智慧不再幻想出新的元件。它不再從頭開始設計按鈕。

相反,設計師和開發人員提供了一個結構化的 UI 元素庫,例如卡片、圖表、模式、文字區塊、表單等。

這些是經過批准的可重複使用元件。 AI只需根據佈局和品牌約束,從這些模組中進行選擇即可。

✅ 3. AI 層組裝 UI。

利用可用的上下文和預先定義的 UI 庫,AI 層產生適合當前情況的結構化 UI 規格。

它定義了要渲染哪些元件、如何排列它們以及要傳遞哪些屬性或資料。例如Render a balance chart at the top, followed by a currency selector and a transfer form pre-filled with the last used account.

人工智慧可能會使用經過訓練的機器學習模型、簡單的啟發式方法,甚至兩者兼而有之來做出這些決策。例如: If the system detects visually impaired users, it automatically enables high-contrast mode

隨著使用者環境的變化,介面也會隨之更新。

它是如何工作的

現在我們已經從概念上了解了生成式 UI 的工作原理,讓我們繼續討論 Thesys 的技術方面以及它如何使這一切成為可能。


2.Thesys 如何使用 C1 API 和 GenUI React SDK 運作。

如您現在所知,Thesys 是一個用於建立生成式 UI 應用程式的開發者平台。它支援多個 LLM,例如 OpenAI 和 Anthropic。

涉及兩個主要元件:

✅ 1)C1 API(LLM 後端)

當您向 C1 API 發送提示時,它會傳回基於 JSON 的 UI 規格(JSON/XML)而不是純文字。

它與 OpenAI 完全相容(相同的端點/參數),因此您可以使用任何 OpenAI 客戶端(JS 或 Python SDK)呼叫它,只需將您的baseURL指向:

https://api.thesys.dev/v1/embed

然後,您可以使用訊息呼叫client.chat.completions.create({...}) 。使用特殊的模型名稱(例如"c1-nightly" ),Thesys API 將呼叫 LLM 並傳回 UI 規格。

client.chat.completions.create({
  model: "c1-nightly",
  messages: [...],
});

c1 API

根據您的使用情況,您可以透過兩種方式使用 C1:

a)將現有的 LLM 替換為 C1,以便優先處理 UI 問題

如果您正在建立新應用程式並希望將延遲降至最低,您可以直接向c1-nightly發送提示,它會立即返回要呈現的 UI 規格。

b)在目前 LLM 堆疊之上加入 C1

如果您已經擁有 LLM 管線(聊天機器人/代理程式),您可以將其輸出傳遞給 C1,作為第二步,產生視覺化佈局。這將在現有流程的基礎上加入更豐富的 UI,而無需更改核心邏輯。

✅ 2)GenUI SDK(前端)

一旦您從 C1 收到 UI 規範,GenUI SDK 就會處理前端的渲染。

該 SDK 是一個 React 框架(基於Crayon 的元件庫建置),它讀取基於 JSON 的 UI 規格並將其映射到視覺化元件。

其核心是<C1Component> (以及用於聊天介面的<C1Chat> ),它接受C1 API回應並將其轉換為即時UI。

以下是範例程式碼:

import { C1Component, ThemeProvider } from "@thesys/genui-sdk";

const App = () => {
  const response = await fetch("<your-backend-url>");
  return (
    <ThemeProvider>
      <C1Component c1Response={response.text()} />
    </ThemeProvider>
  );
};

您可以在文件中閱讀更多內容並在操場上進行現場嘗試。

這就是 C1 和 React SDK 如何協同工作以將 LLM 回應即時轉換為即時 UI。


  1. 使用 Thesys 建立生成式 UI 的逐步指南。

在本節中,我們將討論如何使用 Thesys 的完整流程。我將使用 Next.js。

為了保持實用性,我們將使用 C1 和 Thesys GenUI SDK 建立一個基於表單的工作助理。

這可以讓你建構:

  • 提示驅動的使用者介面,使用者可以要求如下操作:

  • “我想訂購一條圍巾”

  • “給我看看庫存裡的帽子”

  • 然後 LLM 產生 UI 結構(輸入、選擇、按鈕)。

  • 表單資料透過定義的工具提交回助手。

我們開始做吧。

步驟 1:建立 Next.js 應用程式並取得 API 金鑰

我們將從頭開始整合。如果您還沒有 Next.js 應用程式,可以使用此命令進行安裝。

npx create-next-app@latest thesys-demo

安裝 next.js 應用程式

這是我們將要遵循的專案結構。

文件結構

您需要從C1 控制台建立新的 API 金鑰,以將其設定為環境變數。請依照以下約定將此 API 金鑰新增至.env檔。

THESYS_API_KEY=<your-api-key>

API 金鑰

步驟 2:在前端渲染聊天 UI

我們需要一個基本的聊天介面,其UI由提示符號產生。以下是在src/app/page.tsx檔案中使用<C1Chat>實作此功能的方法。

<C1Component />只需要來自 C1 API 的原始 JSON/文本,但對於聊天應用程式,建議使用<C1Chat>元件,因為它支援訊息流。

'use client'

import '@crayonai/react-ui/styles/index.css'
import { C1Chat } from '@thesysai/genui-sdk'

export default function Home() {
  return <C1Chat theme={{ mode: 'dark' }} apiUrl="/api/chat" />
}

程式碼的作用如下:

  • 使用<C1Chat />元件來呈現完整的聊天UI。

  • apiUrl指向將處理提示提交的後端路由。

如您所見,這是整個前端,無需手動 HTML 或表單程式碼。

步驟3:記憶體訊息儲存工具

表單資料將透過自訂tools提交回助手。我們將建立自訂工具,例如createOrdergetInventoryin-memory message store

為了處理表單資料並維護對話上下文,我們首先要建立一個訊息儲存。此工具可協助按執行緒儲存助手的訊息。

安裝openai軟體套件。它是用於與 OpenAI API(例如 GPT-4 或與 OpenAI 相容的 Thesys C1)互動的官方 Node.js SDK。

npm install openai

使用以下程式碼在src/app/api/chat/messageStore.ts建立一個新檔案。

import OpenAI from 'openai'

export type DBMessage = OpenAI.Chat.ChatCompletionMessageParam & {
  id?: string
}

const messagesStore: {
  [threadId: string]: DBMessage[]
} = {}

export const getMessageStore = (id: string) => {
  if (!messagesStore[id]) {
    messagesStore[id] = []
  }
  const messageList = messagesStore[id]
  return {
    addMessage: (message: DBMessage) => {
      messageList.push(message)
    },
    messageList,
    getOpenAICompatibleMessageList: () => {
      return messageList.map((m) => {
        const message = {
          ...m,
        }
        delete message.id
        return message
      })
    },
  }
}

以下是程式碼每個部分的作用:

  • 維護記憶體中的聊天訊息存儲,按threadId組織。

  • messagesStore是一個普通的 JS 物件,它將每個threadId映射到一個訊息陣列。

  • 公開一個實用程式getMessageStore(threadId)該實用程式傳回幫助程式以:

  • addMessage(message) → 新增訊息至執行緒。

  • messageList →傳回線程的所有儲存的訊息。

  • getOpenAICompatibleMessageList() → 傳回不含id欄位的訊息列表,使其與 OpenAI 的ChatCompletion API 相容。

該儲存並非持久化,因為伺服器重新啟動後所有內容都會遺失。您可以將其替換為資料庫(Redis、PostgreSQL)以供生產使用。

步驟4:訂單管理工具

該工具將幫助助理建立並列出手套、帽子、圍巾等不同產品的客戶訂單。它使用Zod進行執行時驗證和模式安全,並將訂單儲存在記憶體中。

您無需安裝 zod,因為它是傳遞依賴項。如果您檢查它的package.json檔案(位於node_modules/@thesysai/genui-sdk/package.json ),您可能會發現類似以下內容:

"dependencies": {
  "zod": "^3.24.1"
}

正版 SDK

使用以下程式碼在src/app/api/chat/orderManagement.ts建立一個新檔案。

import { z } from 'zod'

export const gloveOrderSchema = z.object({
  kind: z.literal('gloves'),
  quantity: z.number(),
  unit: z.enum(['boxes', 'pairs']),
  deliveryDate: z.string(),
  shipping: z.enum(['normal', 'express']),
})

export const hats = z.object({
  kind: z.literal('hats'),
  quantity: z.number(),
  variants: z.enum(['top', 'beanie', 'cap']),
  deliveryDate: z.string(),
  shipping: z.enum(['normal', 'express']),
})

export const scarfOrderSchema = z.object({
  kind: z.literal('scarves'),
  quantity: z.number(),
  colors: z.enum(['red', 'blue', 'green', 'yellow', 'purple', 'orange']),
  deliveryDate: z.string(),
  shipping: z.enum(['normal', 'express']),
})

export const orderSchema = z.object({
  order: z.discriminatedUnion('kind', [
    gloveOrderSchema,
    hats,
    scarfOrderSchema,
  ]),
})

type Order = z.infer<typeof orderSchema>

const orders: Order['order'][] = []

export const createOrder = async (orderJson: unknown) => {
  const order = orderSchema.safeParse(orderJson)
  if (!order.success) {
    console.error('Invalid order', order.error)
    return {
      success: false,
      error: order.error.message,
    }
  }
  const deliveryDate = new Date(order.data.order.deliveryDate)
  console.log('Creating order', { ...order.data.order, deliveryDate })
  orders.push(order.data.order)
  return {
    success: true,
  }
}

export const getOrderSchema = z.object({
  number: z.number().optional().default(10),
})

export const getOrders = (params: unknown) => {
  const parsedParams = getOrderSchema.safeParse(params)
  if (!parsedParams.success) {
    console.error('Invalid params', parsedParams.error)
    return {
      success: false,
      error: parsedParams.error.message,
    }
  }
  return {
    success: true,
    orders: orders.slice(0, parsedParams.data.number),
  }
}

程式碼的作用如下:

  • 支援使用獨特模式欄位動態建立gloveshatsscarves的訂單。

  • 使用z.discriminatedUnion("kind", [...])依照kind排序。以便在一個統一的模式中推理多種產品形式。

  • 定義一個頂級orderSchema ,它包裝各個模式並確保輸入與有效訂單類型之一相符。

  • 建立一個記憶體陣列orders[]來暫時儲存傳入的訂單。

  • 公開createOrder()函數:

  • 接受原始輸入( orderJson

  • 使用 Zod 進行解析和驗證

  • 如果有效,則記錄並儲存訂單

  • 返回成功/失敗回應

  • 公開getOrders()函數:

  • 接受可選的number參數(預設值:10)

  • 返回最新的n訂單

  • 有助於列出聊天或使用者介面中最近的使用者操作

  • 我們在建立和檢索時都使用了safeParse()來防止因錯誤輸入而導致的執行時間崩潰。

步驟5:庫存查詢工具

讓我們建立一個工具,幫助助手根據手套、帽子、圍巾或所有類型獲取可用的產品庫存。

使用以下程式碼在src/app/api/chat/inventory.ts建立一個新檔案。我使用模擬資料,因為我們只是在本地使用。

import { z } from 'zod'

export const inventoryQuerySchema = z.object({
  productType: z
    .enum(['gloves', 'hats', 'scarves', 'all'])
    .optional()
    .default('all'),
})

const allInventory = [
  {
    productType: 'gloves',
    quantity: 100,
    priceInUSD: 10.0,
    urgentDeliveryDate: '2025-04-15',
    normalDeliveryDate: '2025-04-20',
    imageSrc: 'https://images.unsplash.com/photo-1617118602199-d3c05ae37ed8',
  },
  {
    productType: 'hats',
    quantity: 200,
    priceInUSD: 15.0,
    urgentDeliveryDate: '2025-04-15',
    normalDeliveryDate: '2025-04-20',
    imageSrc: 'https://images.unsplash.com/photo-1556306535-0f09a537f0a3',
  },
  {
    productType: 'scarves',
    quantity: 300,
    priceInUSD: 5.0,
    urgentDeliveryDate: '2025-04-15',
    normalDeliveryDate: '2025-04-20',
    imageSrc: 'https://images.unsplash.com/photo-1457545195570-67f207084966',
  },
]

export const getInventory = (params: unknown) => {
  const parsedParams = inventoryQuerySchema.safeParse(params)
  if (!parsedParams.success) {
    console.error('Invalid params', parsedParams.error)
    return { success: false, error: parsedParams.error.message }
  }
  return {
    success: true,
    inventory: allInventory.filter(
      (item) =>
        parsedParams.data.productType === 'all' ||
        item.productType === parsedParams.data.productType
    ),
  }
}

上述程式碼的作用如下:

  • 使用 Zod 定義輸入模式inventoryQuerySchema

  • 接受可選的productType欄位( "gloves""hats""scarves""all"

  • 如果未提供,則預設為"all"

  • 聲明一個包含模擬資料的靜態allInventory陣列。每件商品包含數量、價格、出貨日期和圖片(這些資料可能來自資料庫或 API)。

  • 導出getInventory(params)函數:

  • 使用safeParse()驗證輸入

  • 如果指定,請按類型過濾庫存

  • success: true響應

  • 如果輸入無效,則傳回錯誤訊息

在回答「哪些帽子有貨?」或「顯示所有產品」等查詢時,它將顯示可用的商品以及價格和運送資訊。

步驟 6:使用聊天 API 路由的後端

現在我們需要一個簡單的後端來處理使用與OpenAI-compatible API 呼叫。

現在我們需要建立一個後端來處理 AI 互動( /api/chat ),使用與OpenAI-compatible API 呼叫和串流響應並支援自訂工具。

在建構後端之前,我們先來了解系統提示,它是C1行為控制的關鍵部分。

雖然 C1 本身就很強大,但用合適的提示引導 LLM 學習對於獲得一致的 UI 至關重要。 Thesys 支援系統提示,以便:

  • 定義助理的角色(例如“你是樂於助人的庫存經理”)或特定的語氣/語言

  • 指定渲染行為(例如始終在清單中包含圖像)

  • 使用<ui_rules>標籤強制執行格式規則

閱讀官方文件,了解如何向 AI 應用程式加入系統提示的逐步指南

以下是官方文件中的範例。實際操作中,你應該在每個 API 呼叫前加入此提示:

const systemPrompt = `
You are a data assistant. Use tables for related info,
charts for comparisons, and carousels for lists of items.
`;

const resp = await client.chat.completions.create({
  model: 'c1-nightly',
  messages: [
    { role: 'system', content: systemPrompt },
    { role: 'user', content: userQuery }
  ],
  stream: true
});

以下是src/app/api/chat/route.ts的程式碼。

import { NextRequest, NextResponse } from 'next/server'
import OpenAI from 'openai'
import { transformStream } from '@crayonai/stream'
import { DBMessage, getMessageStore } from './messageStore'
import {
  createOrder,
  getOrders,
  getOrderSchema,
  orderSchema,
} from './orderManagement'
import { zodToJsonSchema } from 'zod-to-json-schema'
import { JSONSchema } from 'openai/lib/jsonschema.mjs'
import { inventoryQuerySchema } from './inventory'
import { getInventory } from './inventory'

const SYSTEM_MESSAGE = `
You are a helpful assistant who can help with placing orders and checking inventory.

<ui_rules>
- When showing inventory, use the list component to show the inventory along with its image.
  Always add the imageSrc to the list component.
</ui_rules>
`

export async function POST(req: NextRequest) {
  const { prompt, threadId, responseId } = (await req.json()) as {
    prompt: DBMessage
    threadId: string
    responseId: string
  }
  const client = new OpenAI({
    baseURL: 'https://api.thesys.dev/v1/embed/',
    apiKey: process.env.THESYS_API_KEY,
  })
  const messageStore = getMessageStore(threadId)
  if (messageStore.getOpenAICompatibleMessageList().length === 0) {
    messageStore.addMessage({
      role: 'system',
      content: SYSTEM_MESSAGE,
    })
  }

  messageStore.addMessage(prompt)

  const llmStream = client.chat.completions.runTools({ // OpenAI SDK v5+
    model: 'c1-nightly',
    messages: messageStore.getOpenAICompatibleMessageList(),
    stream: true,
    tools: [
      {
        type: 'function',
        function: {
          name: 'createOrder',
          description: 'Create an order',
          parameters: zodToJsonSchema(orderSchema) as JSONSchema,
          function: createOrder,
          parse: JSON.parse,
        },
      },
      {
        type: 'function',
        function: {
          name: 'getOrders',
          description: 'Get all orders',
          parameters: zodToJsonSchema(getOrderSchema) as JSONSchema,
          function: getOrders,
          parse: JSON.parse,
        },
      },
      {
        type: 'function',
        function: {
          name: 'getInventory',
          description: 'Get the current inventory',
          parameters: zodToJsonSchema(inventoryQuerySchema) as JSONSchema,
          function: getInventory,
          parse: JSON.parse,
        },
      },
    ],
  })

  const responseStream = transformStream(
    llmStream,
    (chunk) => {
      return chunk.choices[0].delta.content
    },
    {
      onEnd: ({ accumulated }) => {
        const message = accumulated.filter((message) => message).join('')
        messageStore.addMessage({
          role: 'assistant',
          content: message,
          id: responseId,
        })
      },
    }
  ) as ReadableStream<string>

  return new NextResponse(responseStream, {
    headers: {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache, no-transform',
      Connection: 'keep-alive',
    },
  })
}

上述程式碼的作用如下:

  • 使用使用者提示、線程 ID、回應 ID 處理傳入到/api/chat的 POST 請求。

  • 初始化系統提示,告訴助手如何行為以及如何呈現 UI(顯示庫存時始終包含imageSrc )。

  • 使用getMessageStore()維護記憶體中的聊天歷史記錄,以使訊息保持線程特定並與 OpenAI 相容。

  • 使用runTools()方法呼叫 Thesys 的聊天完成 API ( /v1/embed/ ),該方法:

  • 即時傳輸 LLM 回應。

  • 支援多種自訂工具:

  - `createOrder`: for placing an order
  - `getOrders`: for listing previous orders
  - `getInventory`: for querying stock info
  • 每個工具都使用透過zodToJsonSchema()轉換為 JSON Schema 的zod模式進行註冊,以便 LLM 知道輸入/輸出結構。

  • 使用transformStream()將助手的輸出串流回客戶端:

  • 處理流程以提取 LLM 內容。

  • 累積最終回應並將其儲存在訊息歷史記錄中(使用responseId對其進行標記)。

最後返回text/event-stream回應,讓前端在產生內容時逐步呈現內容。

耶! 🎉您已成功建立生成式 UI。

步驟7:輸出

若要啟動本機開發伺服器,請在終端機中執行npm run dev

現在我們已經連接了前端、後端和所有支援工具,讓我們看看最終的結果。

這是使用者介面的樣子,使用crayonai/react-ui進行樣式設計。

ui介面

你可以自然地與助手互動,例如hiI want to place an order 。 LLM 能夠理解你的提示,並根據你的查詢動態呈現合適的 UI。

每個工具都使用 Zod 進行模式綁定,並使用有效的 UI 區塊即時回應。

如您所見,它列出了選項,甚至提供了按鈕: Place New OrderCheck InventoryView Orders

閒聊

讓我們檢查一下有哪些商品有貨。助手會使用getInventory()工具取得庫存,並渲染包含商品資訊、價格、配送選項(硬編碼值)的卡片。

庫存查詢

點擊「帽子」之類的產品會產生完整的訂單,該訂單由 LLM 根據我們提供的模式即時建立。

助理知道需要哪些輸入、輸入類型,甚至加入下拉式選單、日期選擇器和單選按鈕組等使用者體驗元素,然後由 SDK 渲染。

帽子作為訂單

帽子訂單

一旦提交,表單資料就會傳回給助手,並由適當的後端函數( createOrder() )處理,該函數會儲存結果並確認操作。

它還將列出下達另一個訂單和檢查現有訂單的其他選項。

訂單已確認

您無需編寫任何 HTML 表單,使用者就能獲得功能齊全的輸入欄位和動態流程。生成式 UI 非常酷,能夠解鎖眾多強大的用例。


  1. 所有主要的 AI 堆疊都可以與 Thesys 一起使用。

Thesys 旨在存取現代 AI 堆疊和工作流程。例如:

  • LLM → Anthropic、OpenAI(預覽)、自訂模型(透過結構化 JSON)

  • Client SDKs → 標準 OpenAI 相容客戶端(Python、JS)

  • Chaining Tools → LangChain、LlamaIndex 管道 → C1 渲染 UI

  • Agent Framework → AutoGPT/BabyAGI 代理可以呼叫工具並渲染 UI

  • Backend → 任何 REST 框架,例如 Python、Node.js、FastAPI、Django、Next.js

  • Frontend → 任何 React 框架,例如 Next.js

  • Deployment → Vercel、Netlify、AWS、GCP、您的基礎設施


生成式 UI 是前端的未來。

使用 Thesys,您的前端可以根據上下文做出回應、調整並自行建立。

希望你找到了一些有價值的東西。嘗試一下,建立一些有用的東西。

祝你今天過得愉快!下次見 :)

| 您可以檢查
我在anmolbaranwal.com上工作。
感謝您的閱讀! 🥰 | 嘰嘰喳喳 GitHub 領英 |

| --------- | -------- |

結尾揮手告別的 GIF


原文出處:https://dev.to/anmolbaranwal/thesys-react-sdk-turn-llm-responses-into-real-time-user-interfaces-30d5


共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝8   💬8   ❤️13
402
🥈
我愛JS
📝1   💬6   ❤️4
88
🥉
酷豪
📝1   ❤️1
50
#4
AppleLily
📝1   💬4   ❤️1
38
#5
💬3  
10
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次