/**
* 處理圖片辨識查詢
* @param {string} query - 客戶的查詢
* @param {string} imageUrl - 圖片URL
* @returns {Promise<string>} - 包含回答的文字
*/
async function processImageQuery(query, imageUrl) {
try {
console.log(`處理圖片查詢: "${query}", 圖片: ${imageUrl}`);
// 準備輸入
const input = [
{
role: "user",
content: [
{ type: "input_text", text: query || "這張圖片中有什麼?" },
{ type: "input_image", image_url: imageUrl },
],
},
];
// 發送 AI 請求
const response = await openai.responses.create({
model: "gpt-4o",
input: input,
});
console.log("AI 回應:", response);
// 返回 AI 回答
return response.output_text;
} catch (error) {
console.error("處理圖片查詢出錯:", error);
throw error;
}
}
// API 端點 - 圖片辨識
app.post("/image-analysis", async (req, res) => {
try {
const { message, imageUrl } = req.body;
if (!imageUrl) {
return res.status(400).json({ error: "請提供圖片URL" });
}
const answer = await processImageQuery(message, imageUrl);
if (!answer) {
return res.status(500).json({ error: "無法生成回答" });
}
res.json({ response: answer });
} catch (error) {
console.error("API 錯誤:", error);
res.status(500).json({ error: error.message || "處理圖片查詢時發生錯誤" });
}
});
const PRODUCT_CATEGORIES = ["男裝","女裝","鞋子","3C","玩具","遊戲","煙酒","家具"]
/**
* 生成商品分類標籤
* @param {string} imageUrl - 圖片URL
* @returns {Promise<Object>} - 包含標籤的對象
*/
async function generateProductCategories(imageUrl) {
try {
console.log(`生成商品分類標籤,圖片: ${imageUrl}`);
// 定義可用的函式
const tools = [
{
type: "function",
name: "select_product_categories",
description:
"從預定義的商品分類標籤中選擇最適合的標籤,所有回應必須使用繁體中文",
parameters: {
type: "object",
properties: {
product_name: {
type: "string",
description: "產品名稱(必須使用繁體中文)",
},
product_description: {
type: "string",
description: "產品的簡短描述(必須使用繁體中文)",
},
categories: {
type: "array",
description:
"從預定義分類中選擇的商品分類標籤,最多選擇5個最相關的標籤",
items: {
type: "string",
enum: PRODUCT_CATEGORIES,
},
maxItems: 5,
},
},
required: ["product_name", "product_description", "categories"],
},
},
];
// 準備輸入
const input = [
{
role: "user",
content: [
{
type: "input_text",
text: "請分析這張產品圖片,從預定義的商品分類標籤中選擇最適合的標籤。請選擇最多5個最相關的標籤,並提供簡短的產品描述。請務必使用繁體中文回答,產品名稱和描述都必須是繁體中文。",
},
{ type: "input_image", image_url: imageUrl },
],
},
];
// 發送 AI 請求
const response = await openai.responses.create({
model: "gpt-4o",
input: input,
tools: tools,
tool_choice: "auto",
});
console.log("AI 回應:", response);
// 檢查是否有函式被呼叫
if (response.output && response.output.length > 0) {
const functionCall = response.output.find(
(call) => call.name === "select_product_categories"
);
if (functionCall) {
// 解析函式參數
const args = JSON.parse(functionCall.arguments);
return {
success: true,
data: args,
};
}
}
// 如果沒有函式呼叫,返回錯誤
return {
success: false,
error: "無法生成標籤",
};
} catch (error) {
console.error("生成商品分類標籤出錯:", error);
return {
success: false,
error: error.message,
};
}
}
// API 端點 - 商品分類標籤
app.post("/product-categories", async (req, res) => {
try {
const { imageUrl } = req.body;
if (!imageUrl) {
return res.status(400).json({ error: "請提供圖片URL" });
}
const result = await generateProductCategories(imageUrl);
if (!result.success) {
return res.status(500).json({ error: result.error || "無法生成標籤" });
}
res.json(result);
} catch (error) {
console.error("API 錯誤:", error);
res.status(500).json({ error: error.message || "處理圖片標籤時發生錯誤" });
}
});
OpenAI 的圖像 API 提供以下三大功能:
參數 | 類型 | 必填 | 說明 |
---|---|---|---|
prompt |
string | 是 | 描述希望生成圖像的文字提示。 |
model |
string | 否 | 使用的模型,預設為 dall-e-2 。 |
n |
integer | 否 | 要生成的圖像數量,dall-e-2 支援 1~10,dall-e-3 僅支援 1。 |
size |
string | 否 | 圖像尺寸,dall-e-2 支援 256x256 、512x512 、1024x1024 ;dall-e-3 支援 1024x1024 、1792x1024 、1024x1792 。 |
response_format |
string | 否 | 回應格式,預設為 url ,也可設為 b64_json 以獲取 base64 編碼的圖像。 |
user |
string | 否 | 用戶唯一標識符,有助於監控和濫用檢測。 |
quality |
string | 否 | 圖像品質,dall-e-3 可設為 standard 或 hd 。 |
style |
string | 否 | 圖像風格,dall-e-3 可設為 vivid (生動)或 natural (自然)。 |
req body
{
"prompt": "一隻可愛的白色暹羅貓坐在窗台上,窗外是美麗的日落風景",
"size": "1024x1024"
}
/**
* 生成圖片
* @param {string} prompt - 圖片描述提示
* @param {string} size - 圖片尺寸
* @returns {Promise<string>} - 生成的圖片URL
*/
async function generateImage(prompt, size = "1024x1024") {
try {
console.log(`生成圖片: "${prompt}", 尺寸: ${size}`);
const response = await openai.images.generate({
model: "dall-e-3",
prompt: prompt,
n: 1,
size: size,
quality: "standard",
});
console.log("圖片生成回應:", response);
// 回傳生成的圖片URL
if (response.data && response.data.length > 0) {
return {
url: response.data[0].url,
revised_prompt: response.data[0].revised_prompt,
};
} else {
throw new Error("無法生成圖片");
}
} catch (error) {
console.error("生成圖片出錯:", error);
throw error;
}
}
// API 端點 - 圖片生成
app.post("/image-generation", async (req, res) => {
try {
const { prompt, size } = req.body;
if (!prompt) {
return res.status(400).json({ error: "請提供圖片描述提示" });
}
const validSizes = ["1024x1024", "1024x1792", "1792x1024"];
const imageSize = validSizes.includes(size) ? size : "1024x1024";
const result = await generateImage(prompt, imageSize);
res.json({
image_url: result.url,
revised_prompt: result.revised_prompt,
});
} catch (error) {
console.error("API 錯誤:", error);
res.status(500).json({ error: error.message || "生成圖片時發生錯誤" });
}
});
axios
// 天氣 API 配置
const axios = require("axios");
const WEATHER_API_KEY = process.env.WEATHERAPI_KEY;
const WEATHER_BASE_URL = "https://api.weatherapi.com/v1";
/**
* 取得天氣數據
* @param {string} city - 城市名稱
* @param {number} days - 預報天數 (1-10)
* @returns {Promise<Object>} - 天氣數據
*/
async function getWeatherData(city, days = 7) {
try {
const response = await axios.get(`${WEATHER_BASE_URL}/forecast.json`, {
params: {
key: WEATHER_API_KEY,
q: city,
days: days,
aqi: "yes",
alerts: "yes",
lang: "zh_tw",
},
});
return response.data;
} catch (error) {
console.error("取得天氣數據時出錯:", error);
throw error;
}
}
/**
* 根據城市名稱取得天氣
* @param {string} city - 城市名稱
* @returns {Promise<Object>} - 天氣數據
*/
async function getWeatherByCity(city) {
try {
console.log(`取得城市天氣: ${city}`);
const weatherData = await getWeatherData(city);
return weatherData;
} catch (error) {
console.error("根據城市取得天氣時出錯:", error);
throw error;
}
}
/**
* 處理天氣查詢
* @param {string} query - 用戶的查詢
* @returns {Promise<Object>} - 包含回答和天氣數據的對象
*/
async function processWeatherQuery(query) {
try {
// 定義可用的函式
const tools = [
{
type: "function",
name: "get_weather",
description: "取得指定城市的天氣信息",
parameters: {
type: "object",
properties: {
city: {
type: "string",
description: "城市名稱,例如 taipei, tokyo, new york",
},
days: {
type: "integer",
description: "預報天數 (1-10)",
},
},
required: ["city"],
},
},
];
// 準備輸入
const input = [{ role: "user", content: query }];
console.log(`處理天氣查詢: "${query}"`);
// 第一次 AI 回應
const response = await openai.responses.create({
model: "gpt-4o",
instructions: `你是一個天氣助手,可以回答用戶關於天氣的問題。
當用戶詢問天氣相關問題時,呼叫 get_weather 函式取得天氣數據。
使用繁體中文回答,簡潔友善。`,
input,
tools,
tool_choice: "auto",
});
// 檢查是否有函式被呼叫
if (response.output && response.output.length > 0) {
// 檢查是否是天氣查詢
const weatherCall = response.output.find(
(call) => call.name === "get_weather"
);
if (weatherCall) {
// 取得天氣數據
const args = JSON.parse(weatherCall.arguments);
const city = args.city || "taipei";
const days = args.days || 7;
console.log(`取得城市 "${city}" 的天氣數據`);
const weatherData = await getWeatherByCity(city);
// 將結果傳回 AI
input.push(weatherCall);
input.push({
type: "function_call_output",
call_id: weatherCall.call_id,
output: JSON.stringify(weatherData),
});
// 取得最終回答
const finalResponse = await openai.responses.create({
model: "gpt-4o",
instructions: `你是一個天氣助手,根據提供的天氣數據回答用戶問題。
使用繁體中文回答,簡潔友善。
如果用戶問的是預測性問題(如"會下雨嗎"),根據降雨機率和降水量做出合理判斷。`,
input,
});
return {
query,
city,
answer: finalResponse.output_text,
weatherData,
};
}
}
// 如果沒有函式呼叫,直接返回 AI 回答
return {
query,
answer: response.output_text,
weatherData: null,
};
} catch (error) {
console.error("處理天氣查詢出錯:", error);
throw error;
}
}
// API 端點 - 處理天氣查詢
app.post("/api/weather/query", async (req, res) => {
try {
const { query } = req.body;
if (!query) {
return res.status(400).json({ error: "請提供查詢內容" });
}
console.log(`收到天氣查詢: "${query}"`);
const result = await processWeatherQuery(query);
if (!result.answer) {
return res.status(500).json({ error: "無法生成回答" });
}
res.json(result);
} catch (error) {
console.error("處理天氣查詢時出錯:", error);
res.status(500).json({ error: error.message || "處理查詢時發生錯誤" });
}
});