const fs = require("fs"); const path = require("path"); const https = require("https"); const crypto = require("crypto"); // 腾讯云混元大模型配置 // 请设置环境变量 TENCENT_SECRET_ID 和 TENCENT_SECRET_KEY const SECRET_ID = process.env.TENCENT_SECRET_ID; const SECRET_KEY = process.env.TENCENT_SECRET_KEY; // API配置 const HOST = "hunyuan.tencentcloudapi.com"; const SERVICE = "hunyuan"; const REGION = "ap-guangzhou"; const ACTION = "ChatCompletions"; const VERSION = "2023-09-01"; const MODEL = "hunyuan-lite"; // 使用混元lite模型,可根据需要更换 // 签名相关函数 function sha256(message, secret = "", encoding = "hex") { const hmac = secret ? crypto.createHmac("sha256", secret) : crypto.createHash("sha256"); return hmac.update(message).digest(encoding); } function getDate(timestamp) { const date = new Date(timestamp * 1000); const year = date.getUTCFullYear(); const month = ("0" + (date.getUTCMonth() + 1)).slice(-2); const day = ("0" + date.getUTCDate()).slice(-2); return `${year}-${month}-${day}`; } function generateSignature(secretId, secretKey, host, payload, timestamp) { const date = getDate(timestamp); // 步骤1:拼接规范请求串 const httpRequestMethod = "POST"; const canonicalUri = "/"; const canonicalQueryString = ""; const contentType = "application/json"; const canonicalHeaders = `content-type:${contentType}\nhost:${host}\nx-tc-action:${ACTION.toLowerCase()}\n`; const signedHeaders = "content-type;host;x-tc-action"; const hashedRequestPayload = sha256(payload); const canonicalRequest = `${httpRequestMethod}\n${canonicalUri}\n${canonicalQueryString}\n${canonicalHeaders}\n${signedHeaders}\n${hashedRequestPayload}`; // 步骤2:拼接待签名字符串 const algorithm = "TC3-HMAC-SHA256"; const credentialScope = `${date}/${SERVICE}/tc3_request`; const hashedCanonicalRequest = sha256(canonicalRequest); const stringToSign = `${algorithm}\n${timestamp}\n${credentialScope}\n${hashedCanonicalRequest}`; // 步骤3:计算签名 const secretDate = sha256(date, "TC3" + secretKey, "buffer"); const secretService = sha256(SERVICE, secretDate, "buffer"); const secretSigning = sha256("tc3_request", secretService, "buffer"); const signature = sha256(stringToSign, secretSigning); // 步骤4:拼接Authorization const authorization = `${algorithm} Credential=${secretId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`; return authorization; } // 调用混元API async function callHunyuan(prompt) { return new Promise((resolve, reject) => { const timestamp = Math.floor(Date.now() / 1000); const payload = JSON.stringify({ Model: MODEL, Messages: [ { Role: "user", Content: prompt, }, ], Stream: false, }); const authorization = generateSignature( SECRET_ID, SECRET_KEY, HOST, payload, timestamp ); const options = { hostname: HOST, port: 443, path: "/", method: "POST", headers: { "Content-Type": "application/json", Host: HOST, "X-TC-Action": ACTION, "X-TC-Version": VERSION, "X-TC-Timestamp": timestamp.toString(), "X-TC-Region": REGION, Authorization: authorization, }, }; const req = https.request(options, (res) => { let data = ""; res.on("data", (chunk) => (data += chunk)); res.on("end", () => { try { const result = JSON.parse(data); if (result.Response && result.Response.Choices) { resolve(result.Response.Choices[0].Message.Content.trim()); } else if (result.Response && result.Response.Error) { reject(new Error(result.Response.Error.Message)); } else { reject(new Error("Unknown API response: " + data)); } } catch (e) { reject(e); } }); }); req.on("error", reject); req.write(payload); req.end(); }); } // 为单个汉字生成介绍 async function generateIntroduce(char) { const prompt = `请为汉字"${char}"生成一个简短的词组介绍,格式为"${char},XXX的${char}",其中XXX是一个包含该汉字的常见词语。 例如: - 汉字"天"的介绍是"天,天空的天" - 汉字"地"的介绍是"地,大地的地" - 汉字"人"的介绍是"人,人民的人" 请只输出介绍内容,不要包含其他解释。比如对于"天",只输出"天,天空的天"。`; try { const response = await callHunyuan(prompt); // 清理响应,只保留核心内容 let introduce = response.replace(/["""]/g, "").trim(); // 如果响应包含多余内容,尝试提取核心部分 const match = introduce.match(/.,.+的./); if (match) { introduce = match[0]; } // 确保格式正确:如果没有逗号,添加逗号 if (!introduce.startsWith(char + ",")) { // 尝试提取词组部分 const wordMatch = introduce.match(/(.+的.)/); if (wordMatch) { introduce = `${char},${wordMatch[1]}`; } else { introduce = `${char},${char}字的${char}`; } } return introduce; } catch (error) { console.error(`生成 "${char}" 介绍失败:`, error.message); return `${char},${char}字的${char}`; } } // 延时函数 function delay(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } // 主函数 async function main() { // 检查环境变量 if (!SECRET_ID || !SECRET_KEY) { console.error("请设置环境变量 TENCENT_SECRET_ID 和 TENCENT_SECRET_KEY"); console.error("例如:"); console.error( " export TENCENT_SECRET_ID=your_secret_id" ); console.error( " export TENCENT_SECRET_KEY=your_secret_key" ); process.exit(1); } // 读取汉字数据 const charStringPath = path.join( __dirname, "../data/char/char_string.json" ); const charString = JSON.parse(fs.readFileSync(charStringPath, "utf-8")); // 获取所有汉字 const chars = charString["3500"].split(""); console.log(`共有 ${chars.length} 个汉字需要处理`); // 检查是否有已存在的进度文件 const outputPath = path.join( __dirname, "../data/char/char_introduce.json" ); let results = []; let startIndex = 0; if (fs.existsSync(outputPath)) { try { results = JSON.parse(fs.readFileSync(outputPath, "utf-8")); startIndex = results.length; console.log(`发现已有进度,从第 ${startIndex + 1} 个汉字继续`); } catch (e) { console.log("已有文件解析失败,从头开始"); } } // 批量处理 const BATCH_SIZE = 10; // 每批处理10个 const DELAY_BETWEEN_BATCHES = 1000; // 批次间延迟1秒 for (let i = startIndex; i < chars.length; i += BATCH_SIZE) { const batch = chars.slice(i, Math.min(i + BATCH_SIZE, chars.length)); console.log( `处理第 ${i + 1} - ${Math.min(i + BATCH_SIZE, chars.length)} 个汉字...` ); // 并行处理当前批次 const batchResults = await Promise.all( batch.map(async (char, idx) => { // 每个请求之间稍微错开 await delay(idx * 100); const introduce = await generateIntroduce(char); console.log(` ${char}: ${introduce}`); return { char, introduce }; }) ); results.push(...batchResults); // 每批处理完后保存进度 fs.writeFileSync(outputPath, JSON.stringify(results, null, 2), "utf-8"); console.log(`已保存进度:${results.length}/${chars.length}`); // 批次间延迟,避免API限流 if (i + BATCH_SIZE < chars.length) { await delay(DELAY_BETWEEN_BATCHES); } } console.log(`\n完成!共生成 ${results.length} 个汉字介绍`); console.log(`结果已保存到: ${outputPath}`); } main().catch(console.error);