新增/修改的程式碼
// src/day4_text_to_json.js
import { openai } from "./aiClient.js";
import { PromptBuilder } from "./promptBuilder.js";
import { extractJson, validateBySchema } from "./jsonGuard.js";
/**
* 新聞 → JSON 結構化摘要
* Schema:
* {
* "title": string,
* "summary": string,
* "keywords": string[],
* "category": string, // politics | tech | health | finance | sports | other
* "date": string // YYYY-MM-DD
* }
*/
const schema = {
type: "object",
required: ["title", "summary", "keywords", "category", "date"],
properties: {
title: { type: "string" },
summary: { type: "string" },
keywords: { type: "object" }, // 注意會驗證是 array
category: { type: "string" },
date: { type: "string" }
},
};
export async function newsToJson(articleText) {
const pb = new PromptBuilder()
.setRole("你是一個新聞編輯助手")
.setGoal("將輸入的新聞文章轉換為結構化 JSON 摘要")
.addConstraint("輸出必須是純 JSON,不要有多餘文字或 Markdown")
.addConstraint("keywords 請為 3~5 個字詞陣列")
.addConstraint("category 必須是 politics, tech, health, finance, sports, other 其中之一")
.setJsonSchema(schema)
.setUserInput(articleText);
const res = await openai.chat.completions.create({
model: "gpt-4o-mini",
temperature: 0.2,
messages: pb.toMessages(),
});
const raw = res.choices?.[0]?.message?.content ?? "";
const obj = extractJson(raw);
const check = validateBySchema(obj, schema);
if (!check.ok) {
throw new Error("JSON 不符合 schema:" + check.errors.join("; "));
}
return obj;
}
// index.js
import { englishTeacher, codeReview, sentimentClassify } from "./src/day3_prompt_engineering.js";
import { newsToJson } from "./src/day4_text_to_json.js";
const args = Object.fromEntries(
process.argv.slice(2).reduce((acc, cur, i, arr) => {
if (cur.startsWith("--")) {
const key = cur.replace(/^--/, "");
const val = arr[i + 1] && !arr[i + 1].startsWith("--") ? arr[i + 1] : true;
acc.push([key, val]);
}
return acc;
}, [])
);
async function main() {
const task = args.task || "teacher";
if (task === "teacher") {
const input = args.text || "He go to school every day.";
const out = await englishTeacher(input);
console.log("\n=== 英文老師 ===\n");
console.log(out);
} else if (task === "review") {
const sample =
`function sum(arr){
let s = 0;
for (let i=0;i<arr.length;i++){
s += arr[i]
}
return s
}`;
const out = await codeReview(sample, "javascript");
console.log("\n=== 程式碼審查 ===\n");
console.log(out);
} else if (task === "sentiment") {
const text = args.text || "今天心情糟透了,事情一團亂。";
const out = await sentimentClassify(text);
console.log("\n=== 情緒分類(JSON) ===\n");
console.log(out);
} else if (task === "json_summary") {
const article = args.text || `台北市今天宣布推出全新的智慧交通系統,
透過 AI 與大數據分析來優化紅綠燈號誌,預計將能減少 20% 的交通壅塞。`;
const out = await newsToJson(article);
console.log("\n=== 新聞 JSON 摘要 ===\n");
console.log(out);
} else {
console.log("未知任務,請使用 --task teacher | review | sentiment | json_summary");
}
}
main().catch((e) => {
console.error("發生錯誤:", e.message);
process.exit(1);
});
{
"scripts": {
"day4:json": "node index.js --task json_summary --text \"OpenAI 公布新模型,將大幅提升效能與效率。\""
}
}
如何執行
# 跑新聞 → JSON 摘要
npm run day4:json --silent
輸出結果(範例):
{
"title": "台北市啟動智慧交通系統",
"summary": "台北市政府宣布推出 AI 與大數據驅動的智慧交通系統,預計能有效減少交通壅塞 20%。",
"keywords": ["智慧交通", "AI", "大數據", "紅綠燈優化"],
"category": "tech",
"date": "2025-09-04"
}