diff --git a/README.md b/README.md
index 21e40db..7322875 100644
--- a/README.md
+++ b/README.md
@@ -94,7 +94,7 @@ No installation needed! Try the app directly on our demo site:
[](https://next-ai-drawio.jiang.jp/)
-> Note: Due to high traffic, the demo site currently uses Claude Haiku 4.5. For best results, we recommend self-hosting with Claude Opus 4.5.
+> Note: Due to high traffic, the demo site currently uses minimax-m2. For best results, we recommend self-hosting with Claude Sonnet 4.5 or Claude Opus 4.5.
### Run with Docker (Recommended)
diff --git a/app/about/cn/page.tsx b/app/about/cn/page.tsx
index 3339436..f2941e7 100644
--- a/app/about/cn/page.tsx
+++ b/app/about/cn/page.tsx
@@ -102,7 +102,7 @@ export default function AboutCN() {
{/* Header */}
- 关于扩容与限制{" "}
+ 模型变更与用量限制{" "}
(或者说:我的钱包顶不住了)
@@ -116,13 +116,20 @@ export default function AboutCN() {
AI 接口的频率限制
(TPS/TPM)。一旦超限,系统就会暂停,导致请求失败。
+
+ 由于使用量过高,我已将模型从 Claude 更换为{" "}
+
+ minimax-m2
+
+ ,以降低成本。
+
作为一个
独立开发者
,目前的 API
- 费用全是我自己在掏腰包(纯属为爱发电)。为了保证服务能细水长流,同时也为了避免我个人陷入财务危机,我不得不设置以下临时用量限制:
+ 费用全是我自己在掏腰包(纯属为爱发电)。为了保证服务能细水长流,同时也为了避免我个人陷入财务危机,我还设置了以下临时用量限制:
diff --git a/app/about/ja/page.tsx b/app/about/ja/page.tsx
index 3b6d70d..f4ef4a1 100644
--- a/app/about/ja/page.tsx
+++ b/app/about/ja/page.tsx
@@ -110,7 +110,7 @@ export default function AboutJA() {
{/* Header */}
- 利用制限とスケーリングについて{" "}
+ モデル変更と利用制限について{" "}
(別名:お財布が悲鳴を上げています)
@@ -124,13 +124,21 @@ export default function AboutJA() {
AI API のレート制限 (TPS/TPM)
に頻繁に引っかかってしまっています。制限に達するとシステムが一時停止し、エラーが発生してしまいます。
+
+ 利用量の増加に伴い、コスト削減のためモデルを
+ Claude から{" "}
+
+ minimax-m2
+ {" "}
+ に変更しました。
+
私は現在、
個人開発者
として API
- 費用を全額自腹で負担しています。サービスを継続し、かつ私自身が借金を背負わないようにするため(笑)、一時的に以下の利用制限を設けさせていただきました。
+ 費用を全額自腹で負担しています。サービスを継続し、かつ私自身が借金を背負わないようにするため(笑)、一時的に以下の利用制限も設けさせていただきました。
diff --git a/app/about/page.tsx b/app/about/page.tsx
index 74fbf89..36080f4 100644
--- a/app/about/page.tsx
+++ b/app/about/page.tsx
@@ -110,7 +110,7 @@ export default function About() {
{/* Header */}
- Usage Limits & Scaling{" "}
+ Model Change & Usage Limits{" "}
(Or: Why My Wallet is Crying)
@@ -127,6 +127,14 @@ export default function About() {
(TPS/TPM). When this happens, the system
pauses, leading to failed requests.
+
+ Due to the high usage, I have changed the
+ model from Claude to{" "}
+
+ minimax-m2
+
+ , which is more cost-effective.
+
As an{" "}
@@ -135,7 +143,7 @@ export default function About() {
, I am currently footing the entire API
bill. To keep the lights on and ensure the
service remains available to everyone
- without sending me into debt, I have
+ without sending me into debt, I have also
implemented the following temporary caps:
diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts
index ff073cf..778ce9a 100644
--- a/app/api/chat/route.ts
+++ b/app/api/chat/route.ts
@@ -8,7 +8,7 @@ import {
streamText,
} from "ai"
import { z } from "zod"
-import { getAIModel } from "@/lib/ai-providers"
+import { getAIModel, supportsPromptCaching } from "@/lib/ai-providers"
import { findCachedResponse } from "@/lib/cached-responses"
import {
getTelemetryConfig,
@@ -202,6 +202,12 @@ async function handleChatRequest(req: Request): Promise {
// Get AI model from environment configuration
const { model, providerOptions, headers, modelId } = getAIModel()
+ // Check if model supports prompt caching
+ const shouldCache = supportsPromptCaching(modelId)
+ console.log(
+ `[Prompt Caching] ${shouldCache ? "ENABLED" : "DISABLED"} for model: ${modelId}`,
+ )
+
// Get the appropriate system prompt based on model (extended for Opus/Haiku 4.5)
const systemMessage = getSystemPrompt(modelId)
@@ -262,7 +268,7 @@ ${lastMessageText}
// Add cache point to the last assistant message in conversation history
// This caches the entire conversation prefix for subsequent requests
// Strategy: system (cached) + history with last assistant (cached) + new user message
- if (enhancedMessages.length >= 2) {
+ if (shouldCache && enhancedMessages.length >= 2) {
// Find the last assistant message (should be second-to-last, before current user message)
for (let i = enhancedMessages.length - 2; i >= 0; i--) {
if (enhancedMessages[i].role === "assistant") {
@@ -287,17 +293,21 @@ ${lastMessageText}
{
role: "system" as const,
content: systemMessage,
- providerOptions: {
- bedrock: { cachePoint: { type: "default" } },
- },
+ ...(shouldCache && {
+ providerOptions: {
+ bedrock: { cachePoint: { type: "default" } },
+ },
+ }),
},
// Cache breakpoint 2: Current diagram XML context
{
role: "system" as const,
content: `Current diagram XML:\n"""xml\n${xml || ""}\n"""\nWhen using edit_diagram, COPY search patterns exactly from this XML - attribute order matters!`,
- providerOptions: {
- bedrock: { cachePoint: { type: "default" } },
- },
+ ...(shouldCache && {
+ providerOptions: {
+ bedrock: { cachePoint: { type: "default" } },
+ },
+ }),
},
]
diff --git a/components/chat-panel.tsx b/components/chat-panel.tsx
index 7377c22..0cd83e8 100644
--- a/components/chat-panel.tsx
+++ b/components/chat-panel.tsx
@@ -40,7 +40,7 @@ const STORAGE_TPM_MINUTE_KEY = "next-ai-draw-io-tpm-minute"
import { useDiagram } from "@/contexts/diagram-context"
import { findCachedResponse } from "@/lib/cached-responses"
-import { formatXML } from "@/lib/utils"
+import { formatXML, wrapWithMxFile } from "@/lib/utils"
import { ChatMessageDisplay } from "./chat-message-display"
interface ChatPanelProps {
@@ -340,8 +340,11 @@ export default function ChatPanel({
if (toolCall.toolName === "display_diagram") {
const { xml } = toolCall.input as { xml: string }
+ // Wrap raw XML with full mxfile structure for draw.io
+ const fullXml = wrapWithMxFile(xml)
+
// loadDiagram validates and returns error if invalid
- const validationError = onDisplayChart(xml)
+ const validationError = onDisplayChart(fullXml)
if (validationError) {
console.warn(
@@ -1058,7 +1061,7 @@ Please retry with an adjusted search pattern or use display_diagram if retries a
rel="noopener noreferrer"
>
注意:由于访问量较大,演示站点目前使用 minimax-m2 模型。如需获得最佳效果,建议使用 Claude Sonnet 4.5 或 Claude Opus 4.5 自行部署。
+
一个集成了AI功能的Next.js网页应用,与draw.io图表无缝结合。通过自然语言命令和AI辅助可视化来创建、修改和增强图表。
diff --git a/docs/README_JA.md b/docs/README_JA.md
index b82c549..ef35743 100644
--- a/docs/README_JA.md
+++ b/docs/README_JA.md
@@ -13,6 +13,8 @@
[🚀 ライブデモ](https://next-ai-drawio.jiang.jp/)
+> 注意:アクセス数が多いため、デモサイトでは現在 minimax-m2 モデルを使用しています。最高の結果を得るには、Claude Sonnet 4.5 または Claude Opus 4.5 でのセルフホスティングをお勧めします。
+
AI機能とdraw.ioダイアグラムを統合したNext.jsウェブアプリケーションです。自然言語コマンドとAI支援の可視化により、ダイアグラムを作成、修正、強化できます。
diff --git a/lib/ai-providers.ts b/lib/ai-providers.ts
index 04778f4..8efd8e8 100644
--- a/lib/ai-providers.ts
+++ b/lib/ai-providers.ts
@@ -283,3 +283,17 @@ export function getAIModel(): ModelConfig {
return { model, providerOptions, headers, modelId }
}
+
+/**
+ * Check if a model supports prompt caching.
+ * Currently only Claude models on Bedrock support prompt caching.
+ */
+export function supportsPromptCaching(modelId: string): boolean {
+ // Bedrock prompt caching is supported for Claude models
+ return (
+ modelId.includes("claude") ||
+ modelId.includes("anthropic") ||
+ modelId.startsWith("us.anthropic") ||
+ modelId.startsWith("eu.anthropic")
+ )
+}
diff --git a/lib/utils.ts b/lib/utils.ts
index e179cd0..8c4d4eb 100644
--- a/lib/utils.ts
+++ b/lib/utils.ts
@@ -106,6 +106,32 @@ export function convertToLegalXml(xmlString: string): string {
return result
}
+/**
+ * Wrap XML content with the full mxfile structure required by draw.io.
+ * Handles cases where XML is just , , or already has .
+ * @param xml - The XML string (may be partial or complete)
+ * @returns Full mxfile-wrapped XML string
+ */
+export function wrapWithMxFile(xml: string): string {
+ if (!xml) {
+ return ``
+ }
+
+ // Already has full structure
+ if (xml.includes("${xml}`
+ }
+
+ // Just content - extract inner content and wrap fully
+ const rootContent = xml.replace(/<\/?root>/g, "").trim()
+ return `${rootContent}`
+}
+
/**
* Replace nodes in a Draw.io XML diagram
* @param currentXML - The original Draw.io XML string