mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-01-03 23:02:31 +08:00
Compare commits
9 Commits
feat/tool-
...
feat/add-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45ab934288 | ||
|
|
cd012f5e2f | ||
|
|
d4fb635d98 | ||
|
|
14740e35a8 | ||
|
|
5b31216917 | ||
|
|
c7d0260328 | ||
|
|
d2d4dd01cc | ||
|
|
b4679f6598 | ||
|
|
0d0d553e23 |
118
.github/workflows/claude-code.yml
vendored
118
.github/workflows/claude-code.yml
vendored
@@ -1,118 +0,0 @@
|
|||||||
name: Claude Code
|
|
||||||
|
|
||||||
on:
|
|
||||||
issue_comment:
|
|
||||||
types: [created]
|
|
||||||
pull_request_review_comment:
|
|
||||||
types: [created]
|
|
||||||
issues:
|
|
||||||
types: [opened, assigned]
|
|
||||||
pull_request_review:
|
|
||||||
types: [submitted]
|
|
||||||
pull_request_target:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
claude:
|
|
||||||
if: |
|
|
||||||
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
||||||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
||||||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
|
|
||||||
(github.event_name == 'issues' && contains(github.event.issue.body, '@claude'))
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
pull-requests: write
|
|
||||||
issues: write
|
|
||||||
id-token: write
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Configure AWS Credentials
|
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
|
||||||
with:
|
|
||||||
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
|
|
||||||
aws-region: us-east-1
|
|
||||||
|
|
||||||
- name: Run Claude Code
|
|
||||||
uses: anthropics/claude-code-action@v1
|
|
||||||
with:
|
|
||||||
use_bedrock: "true"
|
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
pr-review:
|
|
||||||
if: github.event_name == 'pull_request_target'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
id-token: write
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Configure AWS Credentials
|
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
|
||||||
with:
|
|
||||||
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
|
|
||||||
aws-region: us-east-1
|
|
||||||
|
|
||||||
- name: Run Claude Code PR Review
|
|
||||||
uses: anthropics/claude-code-action@v1
|
|
||||||
with:
|
|
||||||
use_bedrock: "true"
|
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
allowed_non_write_users: "*"
|
|
||||||
prompt: |
|
|
||||||
REPO: ${{ github.repository }}
|
|
||||||
PR NUMBER: ${{ github.event.pull_request.number }}
|
|
||||||
|
|
||||||
This is a personal project - an AI-powered draw.io diagram generator built with:
|
|
||||||
- Next.js 15 with React 19
|
|
||||||
- Vercel AI SDK (streamText, useChat, tool calling)
|
|
||||||
- Multiple AI providers: Bedrock, Anthropic, OpenAI, Google, Azure, OpenRouter, Ollama
|
|
||||||
|
|
||||||
STEP 1: Check existing comments to avoid duplicates.
|
|
||||||
Run: `gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/comments`
|
|
||||||
|
|
||||||
Build a list of files and line numbers that already have comments. For each existing comment:
|
|
||||||
- If the issue is FIXED in current code, resolve the thread using:
|
|
||||||
`gh api graphql -f query='mutation { resolveReviewThread(input: {threadId: "THREAD_ID"}) { thread { isResolved } } }'`
|
|
||||||
- If the issue still exists, remember this file:line - DO NOT create a new comment for it
|
|
||||||
|
|
||||||
STEP 2: Review the diff for issues, but SKIP any file:line that already has a comment.
|
|
||||||
|
|
||||||
Review this PR for these issues (report ALL that apply):
|
|
||||||
1. Bugs that would cause runtime errors or broken functionality
|
|
||||||
2. Security issues (exposed secrets, API key leaks)
|
|
||||||
3. AI SDK misuse - specifically check for:
|
|
||||||
- Client-side: Should use useChat/useCompletion/useObject hooks, NOT raw fetch()
|
|
||||||
- Server-side: Should use streamText/generateText/streamObject/generateObject
|
|
||||||
- Message handling: Access message.parts array, not legacy content property
|
|
||||||
- Tool definitions: Must use Zod schemas for inputSchema
|
|
||||||
- Status handling: Check status (submitted/streaming/ready/error) before actions
|
|
||||||
- Stream cleanup: Call stop() when aborting streams
|
|
||||||
4. Unrelated changes that should be in separate PRs (scope creep)
|
|
||||||
5. Suspicious .gitignore additions or accidentally committed files
|
|
||||||
6. UI/UX inconsistencies (e.g., alignment issues)
|
|
||||||
|
|
||||||
When reviewing AI SDK usage, fetch https://ai-sdk.dev/docs/ to verify correct patterns.
|
|
||||||
Key doc pages: /docs/ai-sdk-ui/chatbot, /docs/ai-sdk-core/generating-text, /docs/ai-sdk-core/tools-and-tool-calling
|
|
||||||
|
|
||||||
DO NOT comment on:
|
|
||||||
- Minor performance optimizations
|
|
||||||
- Code style preferences (unless clearly wrong)
|
|
||||||
- Type annotations that don't affect functionality
|
|
||||||
|
|
||||||
IMPORTANT:
|
|
||||||
- NEVER create a comment on a file:line that already has a comment - this causes duplicates
|
|
||||||
- For each NEW issue, use `mcp__github_inline_comment__create_inline_comment` to comment on the specific line
|
|
||||||
- ALWAYS include a suggested fix using GitHub's suggestion syntax: ```suggestion\n<fixed code>\n```
|
|
||||||
- Only say "LGTM" if there are truly ZERO new issues to report
|
|
||||||
claude_args: |
|
|
||||||
--allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh api:*),WebFetch(domain:ai-sdk.dev)"
|
|
||||||
11
README.md
11
README.md
@@ -73,6 +73,8 @@ Diagrams are represented as XML that can be rendered in draw.io. The AI processe
|
|||||||
- Google AI
|
- Google AI
|
||||||
- Azure OpenAI
|
- Azure OpenAI
|
||||||
- Ollama
|
- Ollama
|
||||||
|
- OpenRouter
|
||||||
|
- DeepSeek
|
||||||
|
|
||||||
Note that `claude-sonnet-4-5` has trained on draw.io diagrams with AWS logos, so if you want to create AWS architecture diagrams, this is the best choice.
|
Note that `claude-sonnet-4-5` has trained on draw.io diagrams with AWS logos, so if you want to create AWS architecture diagrams, this is the best choice.
|
||||||
|
|
||||||
@@ -105,7 +107,7 @@ cp env.example .env.local
|
|||||||
|
|
||||||
Edit `.env.local` and configure your chosen provider:
|
Edit `.env.local` and configure your chosen provider:
|
||||||
|
|
||||||
- Set `AI_PROVIDER` to your chosen provider (bedrock, openai, anthropic, google, azure, ollama)
|
- Set `AI_PROVIDER` to your chosen provider (bedrock, openai, anthropic, google, azure, ollama, openrouter, deepseek)
|
||||||
- Set `AI_MODEL` to the specific model you want to use
|
- Set `AI_MODEL` to the specific model you want to use
|
||||||
- Add the required API keys for your provider
|
- Add the required API keys for your provider
|
||||||
|
|
||||||
@@ -149,7 +151,8 @@ public/ # Static assets including example images
|
|||||||
- [x] Allow the LLM to modify the XML instead of generating it from scratch everytime.
|
- [x] Allow the LLM to modify the XML instead of generating it from scratch everytime.
|
||||||
- [x] Improve the smoothness of shape streaming updates.
|
- [x] Improve the smoothness of shape streaming updates.
|
||||||
- [x] Add multiple AI provider support (OpenAI, Anthropic, Google, Azure, Ollama)
|
- [x] Add multiple AI provider support (OpenAI, Anthropic, Google, Azure, Ollama)
|
||||||
- [ ] Solve the bug that generation will fail for session that longer than 60s.
|
- [x] Solve the bug that generation will fail for session that longer than 60s.
|
||||||
|
- [ ] Add API config on the UI.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
@@ -161,4 +164,8 @@ For support or inquiries, please open an issue on the GitHub repository or conta
|
|||||||
|
|
||||||
- Email: me[at]jiang.jp
|
- Email: me[at]jiang.jp
|
||||||
|
|
||||||
|
## Star History
|
||||||
|
|
||||||
|
[](https://www.star-history.com/#DayuanJiang/next-ai-draw-io&type=date&legend=top-left)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,13 +1,55 @@
|
|||||||
import { streamText, convertToModelMessages } from 'ai';
|
import { streamText, convertToModelMessages, createUIMessageStream, createUIMessageStreamResponse } from 'ai';
|
||||||
import { getAIModel } from '@/lib/ai-providers';
|
import { getAIModel } from '@/lib/ai-providers';
|
||||||
|
import { findCachedResponse } from '@/lib/cached-responses';
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
export const maxDuration = 60;
|
export const maxDuration = 300;
|
||||||
|
|
||||||
|
// Helper function to check if diagram is minimal/empty
|
||||||
|
function isMinimalDiagram(xml: string): boolean {
|
||||||
|
const stripped = xml.replace(/\s/g, '');
|
||||||
|
return !stripped.includes('id="2"');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to create cached stream response
|
||||||
|
function createCachedStreamResponse(xml: string): Response {
|
||||||
|
const toolCallId = `cached-${Date.now()}`;
|
||||||
|
|
||||||
|
const stream = createUIMessageStream({
|
||||||
|
execute: async ({ writer }) => {
|
||||||
|
writer.write({ type: 'start' });
|
||||||
|
writer.write({ type: 'tool-input-start', toolCallId, toolName: 'display_diagram' });
|
||||||
|
writer.write({ type: 'tool-input-delta', toolCallId, inputTextDelta: xml });
|
||||||
|
writer.write({ type: 'tool-input-available', toolCallId, toolName: 'display_diagram', input: { xml } });
|
||||||
|
writer.write({ type: 'finish' });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return createUIMessageStreamResponse({ stream });
|
||||||
|
}
|
||||||
|
|
||||||
export async function POST(req: Request) {
|
export async function POST(req: Request) {
|
||||||
try {
|
try {
|
||||||
const { messages, xml } = await req.json();
|
const { messages, xml } = await req.json();
|
||||||
|
|
||||||
|
// === CACHE CHECK START ===
|
||||||
|
const isFirstMessage = messages.length === 1;
|
||||||
|
const isEmptyDiagram = !xml || xml.trim() === '' || isMinimalDiagram(xml);
|
||||||
|
|
||||||
|
if (isFirstMessage && isEmptyDiagram) {
|
||||||
|
const lastMessage = messages[0];
|
||||||
|
const textPart = lastMessage.parts?.find((p: any) => p.type === 'text');
|
||||||
|
const filePart = lastMessage.parts?.find((p: any) => p.type === 'file');
|
||||||
|
|
||||||
|
const cached = findCachedResponse(textPart?.text || '', !!filePart);
|
||||||
|
|
||||||
|
if (cached) {
|
||||||
|
console.log('[Cache] Returning cached response for:', textPart?.text);
|
||||||
|
return createCachedStreamResponse(cached.xml);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// === CACHE CHECK END ===
|
||||||
|
|
||||||
const systemMessage = `
|
const systemMessage = `
|
||||||
You are an expert diagram creation assistant specializing in draw.io XML generation.
|
You are an expert diagram creation assistant specializing in draw.io XML generation.
|
||||||
Your primary function is crafting clear, well-organized visual diagrams through precise XML specifications.
|
Your primary function is crafting clear, well-organized visual diagrams through precise XML specifications.
|
||||||
@@ -90,7 +132,30 @@ ${lastMessageText}
|
|||||||
|
|
||||||
// Convert UIMessages to ModelMessages and add system message
|
// Convert UIMessages to ModelMessages and add system message
|
||||||
const modelMessages = convertToModelMessages(messages);
|
const modelMessages = convertToModelMessages(messages);
|
||||||
let enhancedMessages = [...modelMessages];
|
|
||||||
|
// Log messages with empty content for debugging (helps identify root cause)
|
||||||
|
const emptyMessages = modelMessages.filter((msg: any) =>
|
||||||
|
!msg.content || !Array.isArray(msg.content) || msg.content.length === 0
|
||||||
|
);
|
||||||
|
if (emptyMessages.length > 0) {
|
||||||
|
console.warn('[Chat API] Messages with empty content detected:',
|
||||||
|
JSON.stringify(emptyMessages.map((m: any) => ({ role: m.role, contentLength: m.content?.length })))
|
||||||
|
);
|
||||||
|
console.warn('[Chat API] Original UI messages structure:',
|
||||||
|
JSON.stringify(messages.map((m: any) => ({
|
||||||
|
id: m.id,
|
||||||
|
role: m.role,
|
||||||
|
partsCount: m.parts?.length,
|
||||||
|
partTypes: m.parts?.map((p: any) => p.type)
|
||||||
|
})))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter out messages with empty content arrays (Bedrock API rejects these)
|
||||||
|
// This is a safety measure - ideally convertToModelMessages should handle all cases
|
||||||
|
let enhancedMessages = modelMessages.filter((msg: any) =>
|
||||||
|
msg.content && Array.isArray(msg.content) && msg.content.length > 0
|
||||||
|
);
|
||||||
|
|
||||||
// Update the last message with formatted content if it's a user message
|
// Update the last message with formatted content if it's a user message
|
||||||
if (enhancedMessages.length >= 1) {
|
if (enhancedMessages.length >= 1) {
|
||||||
@@ -117,17 +182,49 @@ ${lastMessageText}
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Enhanced messages:", enhancedMessages);
|
// 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) {
|
||||||
|
// 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') {
|
||||||
|
enhancedMessages[i] = {
|
||||||
|
...enhancedMessages[i],
|
||||||
|
providerOptions: {
|
||||||
|
bedrock: { cachePoint: { type: 'default' } },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
break; // Only cache the last assistant message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get AI model from environment configuration
|
// Get AI model from environment configuration
|
||||||
const { model, providerOptions, headers } = getAIModel();
|
const { model, providerOptions, headers } = getAIModel();
|
||||||
|
|
||||||
|
// System message with cache point for Bedrock (requires 1024+ tokens)
|
||||||
|
const systemMessageWithCache = {
|
||||||
|
role: 'system' as const,
|
||||||
|
content: systemMessage,
|
||||||
|
providerOptions: {
|
||||||
|
bedrock: { cachePoint: { type: 'default' } },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const result = streamText({
|
const result = streamText({
|
||||||
model,
|
model,
|
||||||
system: systemMessage,
|
messages: [systemMessageWithCache, ...enhancedMessages],
|
||||||
messages: enhancedMessages,
|
|
||||||
...(providerOptions && { providerOptions }),
|
...(providerOptions && { providerOptions }),
|
||||||
...(headers && { headers }),
|
...(headers && { headers }),
|
||||||
|
onFinish: ({ usage, providerMetadata }) => {
|
||||||
|
console.log('[Cache] Usage:', JSON.stringify({
|
||||||
|
inputTokens: usage?.inputTokens,
|
||||||
|
outputTokens: usage?.outputTokens,
|
||||||
|
cachedInputTokens: usage?.cachedInputTokens,
|
||||||
|
}, null, 2));
|
||||||
|
console.log('[Cache] Provider metadata:', JSON.stringify(providerMetadata, null, 2));
|
||||||
|
},
|
||||||
tools: {
|
tools: {
|
||||||
// Client-side tool that will be executed on the client
|
// Client-side tool that will be executed on the client
|
||||||
display_diagram: {
|
display_diagram: {
|
||||||
|
|||||||
@@ -50,7 +50,10 @@ export default function ExamplePanel({
|
|||||||
{" "}
|
{" "}
|
||||||
You can also upload images to use as references.
|
You can also upload images to use as references.
|
||||||
</p>
|
</p>
|
||||||
<p className="text-sm text-gray-500 mb-2">Try these examples:</p>
|
<p className="text-sm text-gray-500 mb-2">
|
||||||
|
Try these examples{" "}
|
||||||
|
<span className="text-xs text-gray-400">(cached for instant response)</span>:
|
||||||
|
</p>
|
||||||
<div className="flex flex-wrap gap-5">
|
<div className="flex flex-wrap gap-5">
|
||||||
<button
|
<button
|
||||||
className="text-xs bg-gray-100 hover:bg-gray-200 text-gray-800 font-medium py-1 px-2 rounded"
|
className="text-xs bg-gray-100 hover:bg-gray-200 text-gray-800 font-medium py-1 px-2 rounded"
|
||||||
|
|||||||
10
env.example
10
env.example
@@ -1,6 +1,6 @@
|
|||||||
# AI Provider Configuration
|
# AI Provider Configuration
|
||||||
# AI_PROVIDER: Which provider to use
|
# AI_PROVIDER: Which provider to use
|
||||||
# Options: bedrock, openai, anthropic, google, azure, ollama, openrouter
|
# Options: bedrock, openai, anthropic, google, azure, ollama, openrouter, deepseek
|
||||||
# Default: bedrock
|
# Default: bedrock
|
||||||
AI_PROVIDER=bedrock
|
AI_PROVIDER=bedrock
|
||||||
|
|
||||||
@@ -20,16 +20,24 @@ AI_MODEL=global.anthropic.claude-sonnet-4-5-20250929-v1:0
|
|||||||
|
|
||||||
# Anthropic (Direct) Configuration
|
# Anthropic (Direct) Configuration
|
||||||
# ANTHROPIC_API_KEY=sk-ant-...
|
# ANTHROPIC_API_KEY=sk-ant-...
|
||||||
|
# ANTHROPIC_BASE_URL=https://your-custom-anthropic/v1
|
||||||
|
|
||||||
# Google Generative AI Configuration
|
# Google Generative AI Configuration
|
||||||
# GOOGLE_GENERATIVE_AI_API_KEY=...
|
# GOOGLE_GENERATIVE_AI_API_KEY=...
|
||||||
|
# GOOGLE_BASE_URL=https://generativelanguage.googleapis.com/v1beta # Optional: Custom endpoint
|
||||||
|
|
||||||
# Azure OpenAI Configuration
|
# Azure OpenAI Configuration
|
||||||
# AZURE_RESOURCE_NAME=your-resource-name
|
# AZURE_RESOURCE_NAME=your-resource-name
|
||||||
# AZURE_API_KEY=...
|
# AZURE_API_KEY=...
|
||||||
|
# AZURE_BASE_URL=https://your-resource.openai.azure.com # Optional: Custom endpoint (overrides resourceName)
|
||||||
|
|
||||||
# Ollama (Local) Configuration
|
# Ollama (Local) Configuration
|
||||||
# OLLAMA_BASE_URL=http://localhost:11434/api # Optional, defaults to localhost
|
# OLLAMA_BASE_URL=http://localhost:11434/api # Optional, defaults to localhost
|
||||||
|
|
||||||
# OpenRouter Configuration
|
# OpenRouter Configuration
|
||||||
# OPENROUTER_API_KEY=sk-or-v1-...
|
# OPENROUTER_API_KEY=sk-or-v1-...
|
||||||
|
# OPENROUTER_BASE_URL=https://openrouter.ai/api/v1 # Optional: Custom endpoint
|
||||||
|
|
||||||
|
# DeepSeek Configuration
|
||||||
|
# DEEPSEEK_API_KEY=sk-...
|
||||||
|
# DEEPSEEK_BASE_URL=https://api.deepseek.com/v1 # Optional: Custom endpoint
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import { bedrock } from '@ai-sdk/amazon-bedrock';
|
import { bedrock } from '@ai-sdk/amazon-bedrock';
|
||||||
import { openai, createOpenAI } from '@ai-sdk/openai';
|
import { openai, createOpenAI } from '@ai-sdk/openai';
|
||||||
import { anthropic } from '@ai-sdk/anthropic';
|
import { createAnthropic } from '@ai-sdk/anthropic';
|
||||||
import { google } from '@ai-sdk/google';
|
import { google, createGoogleGenerativeAI } from '@ai-sdk/google';
|
||||||
import { azure } from '@ai-sdk/azure';
|
import { azure, createAzure } from '@ai-sdk/azure';
|
||||||
import { ollama } from 'ollama-ai-provider-v2';
|
import { ollama, createOllama } from 'ollama-ai-provider-v2';
|
||||||
import { createOpenRouter } from '@openrouter/ai-sdk-provider';
|
import { createOpenRouter } from '@openrouter/ai-sdk-provider';
|
||||||
|
import { deepseek, createDeepSeek } from '@ai-sdk/deepseek';
|
||||||
|
|
||||||
export type ProviderName =
|
export type ProviderName =
|
||||||
| 'bedrock'
|
| 'bedrock'
|
||||||
@@ -13,7 +14,8 @@ export type ProviderName =
|
|||||||
| 'google'
|
| 'google'
|
||||||
| 'azure'
|
| 'azure'
|
||||||
| 'ollama'
|
| 'ollama'
|
||||||
| 'openrouter';
|
| 'openrouter'
|
||||||
|
| 'deepseek';
|
||||||
|
|
||||||
interface ModelConfig {
|
interface ModelConfig {
|
||||||
model: any;
|
model: any;
|
||||||
@@ -45,6 +47,7 @@ function validateProviderCredentials(provider: ProviderName): void {
|
|||||||
azure: 'AZURE_API_KEY',
|
azure: 'AZURE_API_KEY',
|
||||||
ollama: null, // No credentials needed for local Ollama
|
ollama: null, // No credentials needed for local Ollama
|
||||||
openrouter: 'OPENROUTER_API_KEY',
|
openrouter: 'OPENROUTER_API_KEY',
|
||||||
|
deepseek: 'DEEPSEEK_API_KEY',
|
||||||
};
|
};
|
||||||
|
|
||||||
const requiredVar = requiredEnvVars[provider];
|
const requiredVar = requiredEnvVars[provider];
|
||||||
@@ -60,7 +63,7 @@ function validateProviderCredentials(provider: ProviderName): void {
|
|||||||
* Get the AI model based on environment variables
|
* Get the AI model based on environment variables
|
||||||
*
|
*
|
||||||
* Environment variables:
|
* Environment variables:
|
||||||
* - AI_PROVIDER: The provider to use (bedrock, openai, anthropic, google, azure, ollama, openrouter)
|
* - AI_PROVIDER: The provider to use (bedrock, openai, anthropic, google, azure, ollama, openrouter, deepseek)
|
||||||
* - AI_MODEL: The model ID/name for the selected provider
|
* - AI_MODEL: The model ID/name for the selected provider
|
||||||
*
|
*
|
||||||
* Provider-specific env vars:
|
* Provider-specific env vars:
|
||||||
@@ -72,6 +75,8 @@ function validateProviderCredentials(provider: ProviderName): void {
|
|||||||
* - AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY: AWS Bedrock credentials
|
* - AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY: AWS Bedrock credentials
|
||||||
* - OLLAMA_BASE_URL: Ollama server URL (optional, defaults to http://localhost:11434)
|
* - OLLAMA_BASE_URL: Ollama server URL (optional, defaults to http://localhost:11434)
|
||||||
* - OPENROUTER_API_KEY: OpenRouter API key
|
* - OPENROUTER_API_KEY: OpenRouter API key
|
||||||
|
* - DEEPSEEK_API_KEY: DeepSeek API key
|
||||||
|
* - DEEPSEEK_BASE_URL: DeepSeek endpoint (optional)
|
||||||
*/
|
*/
|
||||||
export function getAIModel(): ModelConfig {
|
export function getAIModel(): ModelConfig {
|
||||||
const provider = (process.env.AI_PROVIDER || 'bedrock') as ProviderName;
|
const provider = (process.env.AI_PROVIDER || 'bedrock') as ProviderName;
|
||||||
@@ -115,33 +120,74 @@ export function getAIModel(): ModelConfig {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'anthropic':
|
case 'anthropic':
|
||||||
model = anthropic(modelId);
|
const customProvider = createAnthropic({
|
||||||
|
apiKey: process.env.ANTHROPIC_API_KEY,
|
||||||
|
baseURL: process.env.ANTHROPIC_BASE_URL || 'https://api.anthropic.com/v1',
|
||||||
|
headers: ANTHROPIC_BETA_HEADERS,
|
||||||
|
});
|
||||||
|
model = customProvider(modelId);
|
||||||
// Add beta headers for fine-grained tool streaming
|
// Add beta headers for fine-grained tool streaming
|
||||||
headers = ANTHROPIC_BETA_HEADERS;
|
headers = ANTHROPIC_BETA_HEADERS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'google':
|
case 'google':
|
||||||
model = google(modelId);
|
if (process.env.GOOGLE_BASE_URL) {
|
||||||
|
const customGoogle = createGoogleGenerativeAI({
|
||||||
|
apiKey: process.env.GOOGLE_GENERATIVE_AI_API_KEY,
|
||||||
|
baseURL: process.env.GOOGLE_BASE_URL,
|
||||||
|
});
|
||||||
|
model = customGoogle(modelId);
|
||||||
|
} else {
|
||||||
|
model = google(modelId);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'azure':
|
case 'azure':
|
||||||
model = azure(modelId);
|
if (process.env.AZURE_BASE_URL) {
|
||||||
|
const customAzure = createAzure({
|
||||||
|
apiKey: process.env.AZURE_API_KEY,
|
||||||
|
baseURL: process.env.AZURE_BASE_URL,
|
||||||
|
});
|
||||||
|
model = customAzure(modelId);
|
||||||
|
} else {
|
||||||
|
model = azure(modelId);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'ollama':
|
case 'ollama':
|
||||||
model = ollama(modelId);
|
if (process.env.OLLAMA_BASE_URL) {
|
||||||
|
const customOllama = createOllama({
|
||||||
|
baseURL: process.env.OLLAMA_BASE_URL,
|
||||||
|
});
|
||||||
|
model = customOllama(modelId);
|
||||||
|
} else {
|
||||||
|
model = ollama(modelId);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'openrouter':
|
case 'openrouter':
|
||||||
const openrouter = createOpenRouter({
|
const openrouter = createOpenRouter({
|
||||||
apiKey: process.env.OPENROUTER_API_KEY,
|
apiKey: process.env.OPENROUTER_API_KEY,
|
||||||
|
...(process.env.OPENROUTER_BASE_URL && { baseURL: process.env.OPENROUTER_BASE_URL }),
|
||||||
});
|
});
|
||||||
model = openrouter(modelId);
|
model = openrouter(modelId);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'deepseek':
|
||||||
|
if (process.env.DEEPSEEK_BASE_URL) {
|
||||||
|
const customDeepSeek = createDeepSeek({
|
||||||
|
apiKey: process.env.DEEPSEEK_API_KEY,
|
||||||
|
baseURL: process.env.DEEPSEEK_BASE_URL,
|
||||||
|
});
|
||||||
|
model = customDeepSeek(modelId);
|
||||||
|
} else {
|
||||||
|
model = deepseek(modelId);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Unknown AI provider: ${provider}. Supported providers: bedrock, openai, anthropic, google, azure, ollama, openrouter`
|
`Unknown AI provider: ${provider}. Supported providers: bedrock, openai, anthropic, google, azure, ollama, openrouter, deepseek`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
557
lib/cached-responses.ts
Normal file
557
lib/cached-responses.ts
Normal file
@@ -0,0 +1,557 @@
|
|||||||
|
export interface CachedResponse {
|
||||||
|
promptText: string;
|
||||||
|
hasImage: boolean;
|
||||||
|
xml: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CACHED_EXAMPLE_RESPONSES: CachedResponse[] = [
|
||||||
|
{
|
||||||
|
promptText: "Give me a **animated connector** diagram of transformer's architecture",
|
||||||
|
hasImage: false,
|
||||||
|
xml: `<root>
|
||||||
|
<mxCell id="0"/>
|
||||||
|
<mxCell id="1" parent="0"/>
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<mxCell id="title" value="Transformer Architecture" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=20;fontStyle=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="300" y="20" width="250" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Input Embedding (Left - Encoder Side) -->
|
||||||
|
<mxCell id="input_embed" value="Input Embedding" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=11;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="80" y="480" width="120" height="40" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Positional Encoding (Left) -->
|
||||||
|
<mxCell id="pos_enc_left" value="Positional Encoding" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=11;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="80" y="420" width="120" height="40" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Encoder Stack -->
|
||||||
|
<mxCell id="encoder_box" value="ENCODER" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;verticalAlign=top;fontSize=12;fontStyle=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="60" y="180" width="160" height="220" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Multi-Head Attention (Encoder) -->
|
||||||
|
<mxCell id="mha_enc" value="Multi-Head
Attention" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=10;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="80" y="330" width="120" height="50" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Add & Norm 1 (Encoder) -->
|
||||||
|
<mxCell id="add_norm1_enc" value="Add & Norm" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=10;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="80" y="280" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Feed Forward (Encoder) -->
|
||||||
|
<mxCell id="ff_enc" value="Feed Forward" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=10;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="80" y="240" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Add & Norm 2 (Encoder) -->
|
||||||
|
<mxCell id="add_norm2_enc" value="Add & Norm" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=10;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="80" y="200" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Nx label for encoder -->
|
||||||
|
<mxCell id="nx_enc" value="Nx" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=11;fontStyle=2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="30" y="275" width="30" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Output Embedding (Right - Decoder Side) -->
|
||||||
|
<mxCell id="output_embed" value="Output Embedding" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=11;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="650" y="480" width="120" height="40" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Positional Encoding (Right) -->
|
||||||
|
<mxCell id="pos_enc_right" value="Positional Encoding" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=11;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="650" y="420" width="120" height="40" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Decoder Stack -->
|
||||||
|
<mxCell id="decoder_box" value="DECODER" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;verticalAlign=top;fontSize=12;fontStyle=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="630" y="140" width="160" height="260" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Masked Multi-Head Attention (Decoder) -->
|
||||||
|
<mxCell id="masked_mha_dec" value="Masked Multi-Head
Attention" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=10;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="650" y="340" width="120" height="50" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Add & Norm 1 (Decoder) -->
|
||||||
|
<mxCell id="add_norm1_dec" value="Add & Norm" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=10;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="650" y="290" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Multi-Head Attention (Decoder - Cross Attention) -->
|
||||||
|
<mxCell id="mha_dec" value="Multi-Head
Attention" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=10;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="650" y="240" width="120" height="40" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Add & Norm 2 (Decoder) -->
|
||||||
|
<mxCell id="add_norm2_dec" value="Add & Norm" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=10;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="650" y="200" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Feed Forward (Decoder) -->
|
||||||
|
<mxCell id="ff_dec" value="Feed Forward" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=10;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="650" y="160" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Add & Norm 3 (Decoder) -->
|
||||||
|
<mxCell id="add_norm3_dec" value="Add & Norm" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=10;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="650" y="120" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Nx label for decoder -->
|
||||||
|
<mxCell id="nx_dec" value="Nx" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=11;fontStyle=2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="790" y="255" width="30" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Linear -->
|
||||||
|
<mxCell id="linear" value="Linear" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=11;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="650" y="80" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Softmax -->
|
||||||
|
<mxCell id="softmax" value="Softmax" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=11;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="650" y="40" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Output Probabilities -->
|
||||||
|
<mxCell id="output" value="Output Probabilities" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=11;fontStyle=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="640" y="0" width="140" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Animated Connectors - Encoder Side -->
|
||||||
|
<mxCell id="conn1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeWidth=2;strokeColor=#6c8ebf;flowAnimation=1;" edge="1" parent="1" source="input_embed" target="pos_enc_left">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<mxCell id="conn2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeWidth=2;strokeColor=#6c8ebf;flowAnimation=1;" edge="1" parent="1" source="pos_enc_left" target="mha_enc">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<mxCell id="conn3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeWidth=2;strokeColor=#82b366;flowAnimation=1;" edge="1" parent="1" source="mha_enc" target="add_norm1_enc">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<mxCell id="conn4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeWidth=2;strokeColor=#d6b656;flowAnimation=1;" edge="1" parent="1" source="add_norm1_enc" target="ff_enc">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<mxCell id="conn5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeWidth=2;strokeColor=#82b366;flowAnimation=1;" edge="1" parent="1" source="ff_enc" target="add_norm2_enc">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Encoder to Decoder Cross Attention -->
|
||||||
|
<mxCell id="conn_cross" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeWidth=3;strokeColor=#9673a6;flowAnimation=1;dashed=1;" edge="1" parent="1" source="add_norm2_enc" target="mha_dec">
|
||||||
|
<mxGeometry relative="1" as="geometry">
|
||||||
|
<Array as="points">
|
||||||
|
<mxPoint x="400" y="215"/>
|
||||||
|
<mxPoint x="400" y="260"/>
|
||||||
|
</Array>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="cross_label" value="K, V" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=10;fontStyle=1;fillColor=#ffffff;" vertex="1" connectable="0" parent="conn_cross">
|
||||||
|
<mxGeometry x="-0.1" y="1" relative="1" as="geometry">
|
||||||
|
<mxPoint x="10" y="-9" as="offset"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Animated Connectors - Decoder Side -->
|
||||||
|
<mxCell id="conn6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeWidth=2;strokeColor=#d79b00;flowAnimation=1;" edge="1" parent="1" source="output_embed" target="pos_enc_right">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<mxCell id="conn7" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeWidth=2;strokeColor=#d79b00;flowAnimation=1;" edge="1" parent="1" source="pos_enc_right" target="masked_mha_dec">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<mxCell id="conn8" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeWidth=2;strokeColor=#82b366;flowAnimation=1;" edge="1" parent="1" source="masked_mha_dec" target="add_norm1_dec">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<mxCell id="conn9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeWidth=2;strokeColor=#d6b656;flowAnimation=1;" edge="1" parent="1" source="add_norm1_dec" target="mha_dec">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<mxCell id="conn10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeWidth=2;strokeColor=#82b366;flowAnimation=1;" edge="1" parent="1" source="mha_dec" target="add_norm2_dec">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<mxCell id="conn11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeWidth=2;strokeColor=#d6b656;flowAnimation=1;" edge="1" parent="1" source="add_norm2_dec" target="ff_dec">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<mxCell id="conn12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeWidth=2;strokeColor=#82b366;flowAnimation=1;" edge="1" parent="1" source="ff_dec" target="add_norm3_dec">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<mxCell id="conn13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeWidth=2;strokeColor=#b85450;flowAnimation=1;" edge="1" parent="1" source="add_norm3_dec" target="linear">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<mxCell id="conn14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeWidth=2;strokeColor=#b85450;flowAnimation=1;" edge="1" parent="1" source="linear" target="softmax">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<mxCell id="conn15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeWidth=2;strokeColor=#6c8ebf;flowAnimation=1;" edge="1" parent="1" source="softmax" target="output">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Residual Connections (Encoder) -->
|
||||||
|
<mxCell id="res1_enc" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeWidth=1.5;strokeColor=#999999;dashed=1;flowAnimation=1;" edge="1" parent="1" source="mha_enc" target="add_norm1_enc">
|
||||||
|
<mxGeometry relative="1" as="geometry">
|
||||||
|
<Array as="points">
|
||||||
|
<mxPoint x="50" y="355"/>
|
||||||
|
<mxPoint x="50" y="295"/>
|
||||||
|
</Array>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<mxCell id="res2_enc" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeWidth=1.5;strokeColor=#999999;dashed=1;flowAnimation=1;" edge="1" parent="1" source="ff_enc" target="add_norm2_enc">
|
||||||
|
<mxGeometry relative="1" as="geometry">
|
||||||
|
<Array as="points">
|
||||||
|
<mxPoint x="50" y="255"/>
|
||||||
|
<mxPoint x="50" y="215"/>
|
||||||
|
</Array>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Residual Connections (Decoder) -->
|
||||||
|
<mxCell id="res1_dec" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;strokeWidth=1.5;strokeColor=#999999;dashed=1;flowAnimation=1;" edge="1" parent="1" source="masked_mha_dec" target="add_norm1_dec">
|
||||||
|
<mxGeometry relative="1" as="geometry">
|
||||||
|
<Array as="points">
|
||||||
|
<mxPoint x="800" y="365"/>
|
||||||
|
<mxPoint x="800" y="305"/>
|
||||||
|
</Array>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<mxCell id="res2_dec" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;strokeWidth=1.5;strokeColor=#999999;dashed=1;flowAnimation=1;" edge="1" parent="1" source="mha_dec" target="add_norm2_dec">
|
||||||
|
<mxGeometry relative="1" as="geometry">
|
||||||
|
<Array as="points">
|
||||||
|
<mxPoint x="800" y="260"/>
|
||||||
|
<mxPoint x="800" y="215"/>
|
||||||
|
</Array>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<mxCell id="res3_dec" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;strokeWidth=1.5;strokeColor=#999999;dashed=1;flowAnimation=1;" edge="1" parent="1" source="ff_dec" target="add_norm3_dec">
|
||||||
|
<mxGeometry relative="1" as="geometry">
|
||||||
|
<Array as="points">
|
||||||
|
<mxPoint x="800" y="175"/>
|
||||||
|
<mxPoint x="800" y="135"/>
|
||||||
|
</Array>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Input/Output Labels -->
|
||||||
|
<mxCell id="input_label" value="Inputs" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=12;fontStyle=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="110" y="530" width="60" height="20" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<mxCell id="output_label" value="Outputs
(shifted right)" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=12;fontStyle=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="660" y="530" width="100" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</root>`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
promptText: "Replicate this in aws style",
|
||||||
|
hasImage: true,
|
||||||
|
xml: `<root>
|
||||||
|
<mxCell id="0"/>
|
||||||
|
<mxCell id="1" parent="0"/>
|
||||||
|
|
||||||
|
<!-- AWS Cloud Container -->
|
||||||
|
<mxCell id="2" value="AWS" style="sketch=0;outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_aws_cloud;strokeColor=#232F3E;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#232F3E;dashed=0;rounded=1;arcSize=5;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="340" y="40" width="880" height="520" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- User -->
|
||||||
|
<mxCell id="3" value="User" style="sketch=0;outlineConnect=0;fontColor=#232F3E;gradientColor=none;fillColor=#232F3D;strokeColor=none;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=14;fontStyle=0;aspect=fixed;pointerEvents=1;shape=mxgraph.aws4.user;rounded=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="80" y="240" width="78" height="78" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- EC2 Instance -->
|
||||||
|
<mxCell id="4" value="EC2" style="sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#ED7100;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=14;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.ec2;rounded=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="560" y="240" width="78" height="78" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- S3 Bucket -->
|
||||||
|
<mxCell id="5" value="S3" style="sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#7AA116;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=14;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.s3;rounded=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="960" y="120" width="78" height="78" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Bedrock -->
|
||||||
|
<mxCell id="6" value="bedrock" style="sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#01A88D;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=14;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.bedrock;rounded=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="960" y="260" width="78" height="78" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- DynamoDB -->
|
||||||
|
<mxCell id="7" value="DynamoDB" style="sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#C925D1;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=14;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.dynamodb;rounded=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="960" y="400" width="78" height="78" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Arrow: User to EC2 -->
|
||||||
|
<mxCell id="8" value="" style="endArrow=classic;html=1;rounded=0;strokeColor=#232F3E;strokeWidth=2;exitX=1;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="3" target="4">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="400" y="350" as="sourcePoint"/>
|
||||||
|
<mxPoint x="450" y="300" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Arrow: EC2 to S3 -->
|
||||||
|
<mxCell id="9" value="" style="endArrow=classic;html=1;rounded=0;strokeColor=#232F3E;strokeWidth=2;exitX=1;exitY=0.25;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="4" target="5">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="700" y="350" as="sourcePoint"/>
|
||||||
|
<mxPoint x="750" y="300" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Arrow: EC2 to Bedrock -->
|
||||||
|
<mxCell id="10" value="" style="endArrow=classic;html=1;rounded=0;strokeColor=#232F3E;strokeWidth=2;exitX=1;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="4" target="6">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="700" y="350" as="sourcePoint"/>
|
||||||
|
<mxPoint x="750" y="300" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Arrow: EC2 to DynamoDB -->
|
||||||
|
<mxCell id="11" value="" style="endArrow=classic;html=1;rounded=0;strokeColor=#232F3E;strokeWidth=2;exitX=1;exitY=0.75;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="4" target="7">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="700" y="350" as="sourcePoint"/>
|
||||||
|
<mxPoint x="750" y="300" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
</root>`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
promptText: "Replicate this flowchart.",
|
||||||
|
hasImage: true,
|
||||||
|
xml: `<root>
|
||||||
|
<mxCell id="0"/>
|
||||||
|
<mxCell id="1" parent="0"/>
|
||||||
|
|
||||||
|
<!-- Start: Lamp doesn't work -->
|
||||||
|
<mxCell id="2" value="Lamp doesn't work" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffcccc;strokeColor=#000000;strokeWidth=2;fontSize=18;fontStyle=0;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="140" y="40" width="180" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Arrow from start to first decision -->
|
||||||
|
<mxCell id="3" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#000000;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="2" target="4">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Decision: Lamp plugged in? -->
|
||||||
|
<mxCell id="4" value="Lamp<br>plugged in?" style="rhombus;whiteSpace=wrap;html=1;fillColor=#ffff99;strokeColor=#000000;strokeWidth=2;fontSize=18;fontStyle=0;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="130" y="150" width="200" height="200" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Arrow to Plug in lamp (No) -->
|
||||||
|
<mxCell id="5" value="No" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#000000;strokeWidth=2;endArrow=block;endFill=1;fontSize=16;" edge="1" parent="1" source="4" target="6">
|
||||||
|
<mxGeometry x="-0.2" relative="1" as="geometry">
|
||||||
|
<mxPoint as="offset"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Action: Plug in lamp -->
|
||||||
|
<mxCell id="6" value="Plug in lamp" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#99ff99;strokeColor=#000000;strokeWidth=2;fontSize=18;fontStyle=0;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="420" y="220" width="200" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Arrow down to second decision (Yes) -->
|
||||||
|
<mxCell id="7" value="Yes" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#000000;strokeWidth=2;endArrow=block;endFill=1;fontSize=16;" edge="1" parent="1" source="4" target="8">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Decision: Bulb burned out? -->
|
||||||
|
<mxCell id="8" value="Bulb<br>burned out?" style="rhombus;whiteSpace=wrap;html=1;fillColor=#ffff99;strokeColor=#000000;strokeWidth=2;fontSize=18;fontStyle=0;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="130" y="400" width="200" height="200" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Arrow to Replace bulb (Yes) -->
|
||||||
|
<mxCell id="9" value="Yes" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#000000;strokeWidth=2;endArrow=block;endFill=1;fontSize=16;" edge="1" parent="1" source="8" target="10">
|
||||||
|
<mxGeometry x="-0.2" relative="1" as="geometry">
|
||||||
|
<mxPoint as="offset"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Action: Replace bulb -->
|
||||||
|
<mxCell id="10" value="Replace bulb" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#99ff99;strokeColor=#000000;strokeWidth=2;fontSize=18;fontStyle=0;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="420" y="470" width="200" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Arrow down to Repair lamp (No) -->
|
||||||
|
<mxCell id="11" value="No" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#000000;strokeWidth=2;endArrow=block;endFill=1;fontSize=16;" edge="1" parent="1" source="8" target="12">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Action: Repair lamp -->
|
||||||
|
<mxCell id="12" value="Repair lamp" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#99ff99;strokeColor=#000000;strokeWidth=2;fontSize=18;fontStyle=0;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="130" y="650" width="200" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</root>`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
promptText: "Draw a cat for me",
|
||||||
|
hasImage: false,
|
||||||
|
xml: `<root>
|
||||||
|
<mxCell id="0"/>
|
||||||
|
<mxCell id="1" parent="0"/>
|
||||||
|
|
||||||
|
<!-- Cat's head -->
|
||||||
|
<mxCell id="2" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;fillColor=#FFE6CC;strokeColor=#000000;strokeWidth=2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="300" y="150" width="120" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Left ear -->
|
||||||
|
<mxCell id="3" value="" style="triangle;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#000000;strokeWidth=2;rotation=30;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="280" y="120" width="50" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Right ear -->
|
||||||
|
<mxCell id="4" value="" style="triangle;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#000000;strokeWidth=2;rotation=-30;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="390" y="120" width="50" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Left ear inner -->
|
||||||
|
<mxCell id="5" value="" style="triangle;whiteSpace=wrap;html=1;fillColor=#FFB6C1;strokeColor=none;rotation=30;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="290" y="135" width="30" height="35" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Right ear inner -->
|
||||||
|
<mxCell id="6" value="" style="triangle;whiteSpace=wrap;html=1;fillColor=#FFB6C1;strokeColor=none;rotation=-30;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="400" y="135" width="30" height="35" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Left eye -->
|
||||||
|
<mxCell id="7" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;fillColor=#000000;strokeColor=#000000;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="325" y="185" width="15" height="15" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Right eye -->
|
||||||
|
<mxCell id="8" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;fillColor=#000000;strokeColor=#000000;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="380" y="185" width="15" height="15" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Nose -->
|
||||||
|
<mxCell id="9" value="" style="triangle;whiteSpace=wrap;html=1;fillColor=#FFB6C1;strokeColor=#000000;strokeWidth=1;rotation=180;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="350" y="210" width="20" height="15" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Mouth left -->
|
||||||
|
<mxCell id="10" value="" style="curved=1;endArrow=none;html=1;strokeColor=#000000;strokeWidth=2;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="360" y="220" as="sourcePoint"/>
|
||||||
|
<mxPoint x="340" y="235" as="targetPoint"/>
|
||||||
|
<Array as="points">
|
||||||
|
<mxPoint x="355" y="230"/>
|
||||||
|
</Array>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Mouth right -->
|
||||||
|
<mxCell id="11" value="" style="curved=1;endArrow=none;html=1;strokeColor=#000000;strokeWidth=2;" edge="1" parent="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="360" y="220" as="sourcePoint"/>
|
||||||
|
<mxPoint x="380" y="235" as="targetPoint"/>
|
||||||
|
<Array as="points">
|
||||||
|
<mxPoint x="365" y="230"/>
|
||||||
|
</Array>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Left whisker 1 -->
|
||||||
|
<mxCell id="12" value="" style="endArrow=none;html=1;strokeColor=#000000;strokeWidth=1.5;" edge="1" parent="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="310" y="200" as="sourcePoint"/>
|
||||||
|
<mxPoint x="260" y="195" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Left whisker 2 -->
|
||||||
|
<mxCell id="13" value="" style="endArrow=none;html=1;strokeColor=#000000;strokeWidth=1.5;" edge="1" parent="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="310" y="210" as="sourcePoint"/>
|
||||||
|
<mxPoint x="260" y="210" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Left whisker 3 -->
|
||||||
|
<mxCell id="14" value="" style="endArrow=none;html=1;strokeColor=#000000;strokeWidth=1.5;" edge="1" parent="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="310" y="220" as="sourcePoint"/>
|
||||||
|
<mxPoint x="260" y="225" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Right whisker 1 -->
|
||||||
|
<mxCell id="15" value="" style="endArrow=none;html=1;strokeColor=#000000;strokeWidth=1.5;" edge="1" parent="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="410" y="200" as="sourcePoint"/>
|
||||||
|
<mxPoint x="460" y="195" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Right whisker 2 -->
|
||||||
|
<mxCell id="16" value="" style="endArrow=none;html=1;strokeColor=#000000;strokeWidth=1.5;" edge="1" parent="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="410" y="210" as="sourcePoint"/>
|
||||||
|
<mxPoint x="460" y="210" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Right whisker 3 -->
|
||||||
|
<mxCell id="17" value="" style="endArrow=none;html=1;strokeColor=#000000;strokeWidth=1.5;" edge="1" parent="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="410" y="220" as="sourcePoint"/>
|
||||||
|
<mxPoint x="460" y="225" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Body -->
|
||||||
|
<mxCell id="18" value="" style="ellipse;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#000000;strokeWidth=2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="285" y="250" width="150" height="180" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Belly -->
|
||||||
|
<mxCell id="19" value="" style="ellipse;whiteSpace=wrap;html=1;fillColor=#FFFFFF;strokeColor=none;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="315" y="280" width="90" height="120" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Left front paw -->
|
||||||
|
<mxCell id="20" value="" style="ellipse;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#000000;strokeWidth=2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="300" y="410" width="40" height="50" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Right front paw -->
|
||||||
|
<mxCell id="21" value="" style="ellipse;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#000000;strokeWidth=2;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="380" y="410" width="40" height="50" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
<!-- Tail -->
|
||||||
|
<mxCell id="22" value="" style="curved=1;endArrow=none;html=1;strokeColor=#000000;strokeWidth=3;fillColor=#FFE6CC;" edge="1" parent="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="285" y="340" as="sourcePoint"/>
|
||||||
|
<mxPoint x="240" y="260" as="targetPoint"/>
|
||||||
|
<Array as="points">
|
||||||
|
<mxPoint x="260" y="350"/>
|
||||||
|
<mxPoint x="240" y="320"/>
|
||||||
|
<mxPoint x="235" y="290"/>
|
||||||
|
</Array>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
|
||||||
|
</root>`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export function findCachedResponse(
|
||||||
|
promptText: string,
|
||||||
|
hasImage: boolean
|
||||||
|
): CachedResponse | undefined {
|
||||||
|
return CACHED_EXAMPLE_RESPONSES.find(
|
||||||
|
(c) => c.promptText === promptText && c.hasImage === hasImage && c.xml !== ''
|
||||||
|
);
|
||||||
|
}
|
||||||
68
package-lock.json
generated
68
package-lock.json
generated
@@ -11,6 +11,7 @@
|
|||||||
"@ai-sdk/amazon-bedrock": "^3.0.62",
|
"@ai-sdk/amazon-bedrock": "^3.0.62",
|
||||||
"@ai-sdk/anthropic": "^2.0.44",
|
"@ai-sdk/anthropic": "^2.0.44",
|
||||||
"@ai-sdk/azure": "^2.0.69",
|
"@ai-sdk/azure": "^2.0.69",
|
||||||
|
"@ai-sdk/deepseek": "^1.0.30",
|
||||||
"@ai-sdk/google": "^2.0.0",
|
"@ai-sdk/google": "^2.0.0",
|
||||||
"@ai-sdk/openai": "^2.0.19",
|
"@ai-sdk/openai": "^2.0.19",
|
||||||
"@ai-sdk/react": "^2.0.22",
|
"@ai-sdk/react": "^2.0.22",
|
||||||
@@ -155,6 +156,40 @@
|
|||||||
"zod": "^3.25.76 || ^4.1.8"
|
"zod": "^3.25.76 || ^4.1.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@ai-sdk/deepseek": {
|
||||||
|
"version": "1.0.30",
|
||||||
|
"resolved": "https://registry.npmjs.org/@ai-sdk/deepseek/-/deepseek-1.0.30.tgz",
|
||||||
|
"integrity": "sha512-pafNclW9L8Z3WimaRwlpHrGbdeaDE/UklT3rMi2aoRRyrA+s7zGcFuu1zbO2ViLNlKfaS91XZa9MFAPXbIftUA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@ai-sdk/openai-compatible": "1.0.28",
|
||||||
|
"@ai-sdk/provider": "2.0.0",
|
||||||
|
"@ai-sdk/provider-utils": "3.0.18"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"zod": "^3.25.76 || ^4.1.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@ai-sdk/deepseek/node_modules/@ai-sdk/provider-utils": {
|
||||||
|
"version": "3.0.18",
|
||||||
|
"resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.18.tgz",
|
||||||
|
"integrity": "sha512-ypv1xXMsgGcNKUP+hglKqtdDuMg68nWHucPPAhIENrbFAI+xCHiqPVN8Zllxyv1TNZwGWUghPxJXU+Mqps0YRQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@ai-sdk/provider": "2.0.0",
|
||||||
|
"@standard-schema/spec": "^1.0.0",
|
||||||
|
"eventsource-parser": "^3.0.6"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"zod": "^3.25.76 || ^4.1.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@ai-sdk/gateway": {
|
"node_modules/@ai-sdk/gateway": {
|
||||||
"version": "2.0.7",
|
"version": "2.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-2.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-2.0.7.tgz",
|
||||||
@@ -231,6 +266,39 @@
|
|||||||
"zod": "^3.25.76 || ^4.1.8"
|
"zod": "^3.25.76 || ^4.1.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@ai-sdk/openai-compatible": {
|
||||||
|
"version": "1.0.28",
|
||||||
|
"resolved": "https://registry.npmjs.org/@ai-sdk/openai-compatible/-/openai-compatible-1.0.28.tgz",
|
||||||
|
"integrity": "sha512-yKubDxLYtXyGUzkr9lNStf/lE/I+Okc8tmotvyABhsQHHieLKk6oV5fJeRJxhr67Ejhg+FRnwUOxAmjRoFM4dA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@ai-sdk/provider": "2.0.0",
|
||||||
|
"@ai-sdk/provider-utils": "3.0.18"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"zod": "^3.25.76 || ^4.1.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@ai-sdk/openai-compatible/node_modules/@ai-sdk/provider-utils": {
|
||||||
|
"version": "3.0.18",
|
||||||
|
"resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.18.tgz",
|
||||||
|
"integrity": "sha512-ypv1xXMsgGcNKUP+hglKqtdDuMg68nWHucPPAhIENrbFAI+xCHiqPVN8Zllxyv1TNZwGWUghPxJXU+Mqps0YRQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@ai-sdk/provider": "2.0.0",
|
||||||
|
"@standard-schema/spec": "^1.0.0",
|
||||||
|
"eventsource-parser": "^3.0.6"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"zod": "^3.25.76 || ^4.1.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@ai-sdk/openai/node_modules/@ai-sdk/provider-utils": {
|
"node_modules/@ai-sdk/openai/node_modules/@ai-sdk/provider-utils": {
|
||||||
"version": "3.0.17",
|
"version": "3.0.17",
|
||||||
"resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.17.tgz",
|
"resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.17.tgz",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"@ai-sdk/amazon-bedrock": "^3.0.62",
|
"@ai-sdk/amazon-bedrock": "^3.0.62",
|
||||||
"@ai-sdk/anthropic": "^2.0.44",
|
"@ai-sdk/anthropic": "^2.0.44",
|
||||||
"@ai-sdk/azure": "^2.0.69",
|
"@ai-sdk/azure": "^2.0.69",
|
||||||
|
"@ai-sdk/deepseek": "^1.0.30",
|
||||||
"@ai-sdk/google": "^2.0.0",
|
"@ai-sdk/google": "^2.0.0",
|
||||||
"@ai-sdk/openai": "^2.0.19",
|
"@ai-sdk/openai": "^2.0.19",
|
||||||
"@ai-sdk/react": "^2.0.22",
|
"@ai-sdk/react": "^2.0.22",
|
||||||
|
|||||||
Reference in New Issue
Block a user