FAQ

關於 Lens OS SDK 的常見問題。

關於整合和使用 Lens OS SDK 的常見問題解答。

一般問題

Lens OS SDK 和直接使用 OpenAI API 有什麼差別?

Lens OS SDK 提供:

功能OpenAI APILens OS SDK
工具呼叫手動實作內建支援
工作階段管理手動實作內建支援
SSE Streaming手動處理自動
多租戶設定主控台管理
技能系統內建支援

支援哪些 LLM 提供者?

任何與 OpenAI API 格式相容的提供者:

  • OpenAI (GPT-4o, GPT-4o-mini)
  • Azure OpenAI
  • DeepSeek
  • 其他相容 OpenAI 的 API

我的資料會被送到哪裡?

你的資料會被送到:

  • Lens OS API (osapi.ask-lens.ai):用於設定和工作階段儲存
  • LLM 提供者:根據你的 LENS_MODEL_BASE_URL 設定

你的資料不會被送到其他地方。

整合問題

可以用於非 Next.js 專案嗎?

可以,但你需要:

  • 後端:Node.js 相容環境
  • 前端:React 18+
Express.js 範例
import express from "express";
import { createAgentHandler } from "@lens-os/sdk/server";

const app = express();
const handler = createAgentHandler({ /* config */ });

app.post("/api/chat", async (req, res) => {
  const response = await handler.POST(req);
  // Handle SSE response
});

可以同時使用多個工具嗎?

可以,Agent 會自動決定是否呼叫多個工具:

多個工具
// Define multiple tools
toolExecutors: {
  product_search: { /* ... */ },
  user_orders: { /* ... */ },
  ai_page_generate: { /* ... */ },
}

// Agent 會根據使用者需求自動選擇
// 例如:"找 TypeScript 書籍並查看我的訂單"
// → 會依序呼叫 product_search 和 user_orders

如何限制工具呼叫次數?

使用 maxTurns 參數:

限制輪數
createAgentHandler({
  maxTurns: 5,  // 最多 5 次工具呼叫
  // ...
});

前端問題

如何自訂聊天 UI?

useLensAgent 只提供狀態和方法 - UI 完全由你決定:

自訂 UI
const { messages, sendMessage, isLoading } = useLensAgent({ ... });

// 完全自訂的 UI
return (
  <YourCustomChatUI
    messages={messages}
    onSend={sendMessage}
    loading={isLoading}
  />
);

如何處理網路斷線?

重試機制
const { error, sendMessage } = useLensAgent({ ... });

const handleSend = async (message: string) => {
  try {
    await sendMessage(message);
  } catch (err) {
    // 顯示錯誤 + 重試按鈕
    setShowRetry(true);
  }
};

後端問題

如果工具執行逾時怎麼辦?

SDK 預設逾時為 30 秒。對於長時間操作:

處理長時間操作
execute: async (params) => {
  // 1. 立即回傳進度
  return {
    success: true,
    result: {
      message: "處理中,預計需要 1 分鐘...",
      status: "processing",
      taskId: "task-123",
    },
  };

  // 2. 讓使用者稍後查詢狀態
  // "我的任務 task-123 完成了嗎?"
}

如何記錄工具呼叫?

日誌記錄
execute: async (params, context) => {
  const startTime = Date.now();

  console.log("[Tool] Started", {
    tool: "product_search",
    params,
    userId: context?.userId,
    sessionId: context?.sessionId,
  });

  try {
    const result = await doWork(params);

    console.log("[Tool] Completed", {
      duration: Date.now() - startTime,
      resultCount: result.length,
    });

    return { success: true, result };
  } catch (err) {
    console.error("[Tool] Failed", {
      duration: Date.now() - startTime,
      error: err.message,
    });

    return { success: false, error: err.message };
  }
}

安全性問題

API Key 安全嗎?

  • LENS_OS_API_KEY:只在伺服器端使用,絕不會暴露給前端
  • LENS_MODEL_API_KEY:只在伺服器端使用

前端間接呼叫你的 API Route,絕不會直接存取這些 Key。

如何防止未授權存取?

加入認證
// chat/route.ts
import { auth } from "@/auth";

export async function POST(request: Request) {
  const session = await auth();

  if (!session?.user) {
    return new Response("Unauthorized", { status: 401 });
  }

  // 繼續處理...
}

如何實作速率限制?

簡單的速率限制
const rateLimit = new Map<string, number[]>();
const LIMIT = 10;  // 每分鐘 10 次
const WINDOW = 60000;

export async function POST(request: Request) {
  const session = await auth();
  const userId = session?.user?.id;

  if (userId) {
    const now = Date.now();
    const userRequests = rateLimit.get(userId) || [];
    const recentRequests = userRequests.filter(t => now - t < WINDOW);

    if (recentRequests.length >= LIMIT) {
      return new Response("超過速率限制", { status: 429 });
    }

    rateLimit.set(userId, [...recentRequests, now]);
  }

  // 繼續處理...
}

Note

需要更多協助?查看疑難排解指南或聯絡 Lens OS 支援。