From 235f122bd4c56727af012aca82894e890bf5f99c Mon Sep 17 00:00:00 2001 From: monadierickx <126071495+monadierickx@users.noreply.github.com> Date: Tue, 15 Apr 2025 17:12:04 +0200 Subject: [PATCH 01/12] profileName option --- backend/Sources/PlaygroundAPI/App.swift | 6 +++++- .../Sources/PlaygroundAPI/Application+build.swift | 14 +++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/backend/Sources/PlaygroundAPI/App.swift b/backend/Sources/PlaygroundAPI/App.swift index dafc2f2e..b7abd0d3 100644 --- a/backend/Sources/PlaygroundAPI/App.swift +++ b/backend/Sources/PlaygroundAPI/App.swift @@ -28,7 +28,11 @@ struct AppCommand: AsyncParsableCommand, AppArguments { @Option(name: .shortAndLong) var logLevel: Logger.Level? - @Flag var sso = false + @Flag(name: .shortAndLong, help: "Use SSO authentication (default: false))") + var sso: Bool = false + + @Option(name: [.customShort("n"), .long], help: "The name of the profile to use (default: default)") + var profileName: String = "default" func run() async throws { let app = try await buildApplication(self) diff --git a/backend/Sources/PlaygroundAPI/Application+build.swift b/backend/Sources/PlaygroundAPI/Application+build.swift index 08b1f2c5..3dbf8d5a 100644 --- a/backend/Sources/PlaygroundAPI/Application+build.swift +++ b/backend/Sources/PlaygroundAPI/Application+build.swift @@ -28,6 +28,7 @@ public protocol AppArguments { var port: Int { get } var logLevel: Logger.Level? { get } var sso: Bool { get } + var profileName: String { get } } // Request context used by application @@ -46,7 +47,7 @@ public func buildApplication( arguments.logLevel ?? environment.get("LOG_LEVEL").flatMap { Logger.Level(rawValue: $0) } ?? .info - let router = try await buildRouter(useSSO: arguments.sso, logger: logger) + let router = try await buildRouter(useSSO: arguments.sso, logger: logger, profileName: arguments.profileName) let app = Application( router: router, configuration: .init( @@ -59,7 +60,7 @@ public func buildApplication( } /// Build router -func buildRouter(useSSO: Bool, logger: Logger) async throws -> Router { +func buildRouter(useSSO: Bool, logger: Logger, profileName: String) async throws -> Router { let router = Router(context: AppRequestContext.self) // CORS @@ -76,7 +77,7 @@ func buildRouter(useSSO: Bool, logger: Logger) async throws -> Router Router Date: Tue, 15 Apr 2025 19:08:12 +0200 Subject: [PATCH 02/12] backend: converse document --- .gitignore | 3 +++ backend/Sources/PlaygroundAPI/Application+build.swift | 5 +++++ backend/Sources/PlaygroundAPI/Types/Chat.swift | 3 +++ 3 files changed, 11 insertions(+) diff --git a/.gitignore b/.gitignore index 23675b5a..1393e260 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ Package.resolved .serverless .vscode .env +Makefile # backend backend/.DS_Store @@ -27,6 +28,7 @@ backend/.env.* backend/.env backend/img/generated_images backend/.vscode +backend/Makefile # frontend frontend/node_modules @@ -54,3 +56,4 @@ frontend/.vercel frontend/*.tsbuildinfo frontend/next-env.d.ts +frontend/Makefile diff --git a/backend/Sources/PlaygroundAPI/Application+build.swift b/backend/Sources/PlaygroundAPI/Application+build.swift index 3dbf8d5a..83142315 100644 --- a/backend/Sources/PlaygroundAPI/Application+build.swift +++ b/backend/Sources/PlaygroundAPI/Application+build.swift @@ -178,10 +178,15 @@ func buildRouter(useSSO: Bool, logger: Logger, profileName: String) async throws if let imageBytes = input.imageBytes { image = ImageBlock(format: input.imageFormat ?? .jpeg, source: imageBytes) } + var document: DocumentBlock? = nil + if let documentBytes = input.documentBytes, let name = input.documentName { + document = try DocumentBlock(name: name, format: input.documentFormat ?? .pdf, source: documentBytes) + } return try await bedrock.converse( with: model, prompt: input.prompt, image: image, + document: document, history: input.history ?? [], maxTokens: input.maxTokens, temperature: input.temperature, diff --git a/backend/Sources/PlaygroundAPI/Types/Chat.swift b/backend/Sources/PlaygroundAPI/Types/Chat.swift index 22e93813..b5abe28c 100644 --- a/backend/Sources/PlaygroundAPI/Types/Chat.swift +++ b/backend/Sources/PlaygroundAPI/Types/Chat.swift @@ -24,6 +24,9 @@ struct ChatInput: Codable { let history: [Message]? let imageFormat: ImageBlock.Format? let imageBytes: String? + let documentName: String? + let documentFormat: DocumentBlock.Format? + let documentBytes: String? let maxTokens: Int? let temperature: Double? let topP: Double? From 41f7437728aaf42f25afb4b6224675a7cecab9b8 Mon Sep 17 00:00:00 2001 From: monadierickx <126071495+monadierickx@users.noreply.github.com> Date: Wed, 7 May 2025 17:40:32 +0200 Subject: [PATCH 03/12] images displayed in chat, only sent once, cleaner lay-out --- .../chatPlayground/ChatComponent.jsx | 48 ++++++++++++++----- frontend/components/chatPlayground/Human.jsx | 17 +++++-- 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/frontend/components/chatPlayground/ChatComponent.jsx b/frontend/components/chatPlayground/ChatComponent.jsx index 11c16263..90b3f9ce 100644 --- a/frontend/components/chatPlayground/ChatComponent.jsx +++ b/frontend/components/chatPlayground/ChatComponent.jsx @@ -24,6 +24,7 @@ export default function ChatContainer() { const [stopSequenceInput, setStopSequenceInput] = useState(''); const [referenceImage, setReferenceImage] = useState(null); const [previewImage, setPreviewImage] = useState('/placeholder.png'); + const fileInputRef = React.useRef(null); const endpoint = `/foundation-models/chat/${selectedModel.modelId}`; const api = `${GlobalConfig.apiHost}:${GlobalConfig.apiPort}${endpoint}`; @@ -34,6 +35,7 @@ export default function ChatContainer() { const onModelChange = (newModel) => { setSelectedModel(newModel); + clearChat() } const handleMaxTokensChange = (value) => { @@ -126,9 +128,20 @@ export default function ChatContainer() { }; const sendMessage = async () => { - const newMessage = { sender: "Human", message: inputValue }; + const currentImage = previewImage !== '/placeholder.png' ? previewImage : null; + const newMessage = { + sender: "Human", + message: inputValue, + image: currentImage + }; setConversation(prevConversation => [...prevConversation, newMessage]); setInputValue(''); + setReferenceImage(null); + setPreviewImage('/placeholder.png'); + + if (fileInputRef.current) { + fileInputRef.current.value = ''; + } try { setIsLoading(true); @@ -286,7 +299,7 @@ export default function ChatContainer() { {conversation.map((item, i) => item.sender === "Assistant" ? ( ) : ( - + ))} {isLoading ? () : (
)} @@ -315,17 +328,26 @@ export default function ChatContainer() { {/* Reference image with preview */}
- - Reference image +
+ +
+
+ Reference image +
{/* Send button */} diff --git a/frontend/components/chatPlayground/Human.jsx b/frontend/components/chatPlayground/Human.jsx index 34d88275..f627f38f 100644 --- a/frontend/components/chatPlayground/Human.jsx +++ b/frontend/components/chatPlayground/Human.jsx @@ -1,6 +1,7 @@ "use client"; +import Image from 'next/image'; -export default function Human({text}) { +export default function Human({text, image}) { return (
@@ -13,9 +14,19 @@ export default function Human({text}) { className="relative mr-3 text-sm bg-indigo-100 py-2 px-4 shadow rounded-xl" >
{text}
+ {image && ( +
+ Attached image +
+ )}
- ) -} \ No newline at end of file +} From ecf5217bc48758fdc411cdee6f79ef079da47449 Mon Sep 17 00:00:00 2001 From: monadierickx <126071495+monadierickx@users.noreply.github.com> Date: Mon, 12 May 2025 18:27:40 +0200 Subject: [PATCH 04/12] reasoning chat --- backend/Package.swift | 2 +- .../PlaygroundAPI/Application+build.swift | 58 ++- .../Sources/PlaygroundAPI/Types/Chat.swift | 2 + frontend/app/reasoning_chat/loading.js | 15 + frontend/app/reasoning_chat/page.js | 9 + frontend/components/Navigation.jsx | 8 +- .../reasoningChatPlayground/Assistant.jsx | 28 ++ .../reasoningChatPlayground/Human.jsx | 32 ++ .../reasoningChatPlayground/Loader.jsx | 27 ++ .../ModelIndicator.jsx | 14 + .../ReasoningChatComponent.jsx | 392 ++++++++++++++++++ .../ReasoningModelSelector.jsx | 49 +++ frontend/helpers/chatModelData.js | 323 ++++++++++++++- frontend/helpers/reasoningModelData.js | 53 +++ 14 files changed, 981 insertions(+), 31 deletions(-) create mode 100644 frontend/app/reasoning_chat/loading.js create mode 100644 frontend/app/reasoning_chat/page.js create mode 100644 frontend/components/reasoningChatPlayground/Assistant.jsx create mode 100644 frontend/components/reasoningChatPlayground/Human.jsx create mode 100644 frontend/components/reasoningChatPlayground/Loader.jsx create mode 100644 frontend/components/reasoningChatPlayground/ModelIndicator.jsx create mode 100644 frontend/components/reasoningChatPlayground/ReasoningChatComponent.jsx create mode 100644 frontend/components/reasoningChatPlayground/ReasoningModelSelector.jsx create mode 100644 frontend/helpers/reasoningModelData.js diff --git a/backend/Package.swift b/backend/Package.swift index e1fdd855..18c5be79 100644 --- a/backend/Package.swift +++ b/backend/Package.swift @@ -12,7 +12,7 @@ let package = Package( dependencies: [ .package(url: "https://github.com/hummingbird-project/hummingbird.git", from: "2.0.0"), .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.3.0"), - .package(url: "https://github.com/monadierickx/swift-bedrock-library.git", branch: "week16"), + .package(url: "https://github.com/monadierickx/swift-bedrock-library.git", branch: "reasoning"), ], targets: [ .executableTarget( diff --git a/backend/Sources/PlaygroundAPI/Application+build.swift b/backend/Sources/PlaygroundAPI/Application+build.swift index 83142315..9bdc86a9 100644 --- a/backend/Sources/PlaygroundAPI/Application+build.swift +++ b/backend/Sources/PlaygroundAPI/Application+build.swift @@ -77,7 +77,11 @@ func buildRouter(useSSO: Bool, logger: Logger, profileName: String) async throws } // SwiftBedrock - let bedrock = try await BedrockService(useSSO: useSSO, profileName: profileName) + var auth: BedrockAuthentication = .default + if useSSO { + auth = .sso(profileName: profileName) + } + let bedrock = try await BedrockService(authentication: auth) // List models // GET /foundation-models lists all models @@ -176,26 +180,48 @@ func buildRouter(useSSO: Bool, logger: Logger, profileName: String) async throws let input = try await request.decode(as: ChatInput.self, context: context) var image: ImageBlock? = nil if let imageBytes = input.imageBytes { - image = ImageBlock(format: input.imageFormat ?? .jpeg, source: imageBytes) + image = try ImageBlock(format: input.imageFormat ?? .jpeg, source: imageBytes) } var document: DocumentBlock? = nil if let documentBytes = input.documentBytes, let name = input.documentName { document = try DocumentBlock(name: name, format: input.documentFormat ?? .pdf, source: documentBytes) } - return try await bedrock.converse( - with: model, - prompt: input.prompt, - image: image, - document: document, - history: input.history ?? [], - maxTokens: input.maxTokens, - temperature: input.temperature, - topP: input.topP, - stopSequences: input.stopSequences, - systemPrompts: input.systemPrompts, - tools: input.tools, - toolResult: input.toolResult - ) + var builder = try ConverseRequestBuilder(with: model) + .withHistory(input.history ?? []) + .withMaxTokens(input.maxTokens) + .withTemperature(input.temperature) + .withTopP(input.topP) + + if let stopSequences = input.stopSequences, + !stopSequences.isEmpty + { + builder = try builder.withStopSequences(stopSequences) + } + if let systemPrompts = input.systemPrompts, + !systemPrompts.isEmpty + { + builder = try builder.withStopSequences(systemPrompts) + } + if let prompt = input.prompt { + builder = try builder.withPrompt(prompt) + } + if let tools = input.tools { + builder = try builder.withTools(tools) + } + if let toolResult = input.toolResult { + builder = try builder.withToolResult(toolResult) + } + if let document { + builder = try builder.withDocument(document) + } + if let image { + builder = try builder.withImage(image) + } + if let enableReasoning = input.enableReasoning, enableReasoning { + builder = try builder.withReasoning() + .withMaxReasoningTokens(input.maxReasoningTokens) + } + return try await bedrock.converse(with: builder) } catch { logger.info( "An error occured while generating chat", diff --git a/backend/Sources/PlaygroundAPI/Types/Chat.swift b/backend/Sources/PlaygroundAPI/Types/Chat.swift index b5abe28c..a71c4987 100644 --- a/backend/Sources/PlaygroundAPI/Types/Chat.swift +++ b/backend/Sources/PlaygroundAPI/Types/Chat.swift @@ -34,6 +34,8 @@ struct ChatInput: Codable { let systemPrompts: [String]? let tools: [Tool]? let toolResult: ToolResultBlock? + let enableReasoning: Bool? + let maxReasoningTokens: Int? } extension ConverseReply: @retroactive ResponseCodable {} diff --git a/frontend/app/reasoning_chat/loading.js b/frontend/app/reasoning_chat/loading.js new file mode 100644 index 00000000..981dbd33 --- /dev/null +++ b/frontend/app/reasoning_chat/loading.js @@ -0,0 +1,15 @@ +export default function Loading() { + return ( +
+
+
+ + Loading... +
+
+
+ ) +} \ No newline at end of file diff --git a/frontend/app/reasoning_chat/page.js b/frontend/app/reasoning_chat/page.js new file mode 100644 index 00000000..fc4c6e0d --- /dev/null +++ b/frontend/app/reasoning_chat/page.js @@ -0,0 +1,9 @@ +"use client"; + +import ReasoningChatComponent from "@/components/reasoningChatPlayground/ReasoningChatComponent"; + +export default async function Chat() { + return ( + + ) +} diff --git a/frontend/components/Navigation.jsx b/frontend/components/Navigation.jsx index a16db7f7..b18f6472 100644 --- a/frontend/components/Navigation.jsx +++ b/frontend/components/Navigation.jsx @@ -19,10 +19,14 @@ export default function Navigation() { className="flex items-center px-6 py-2 mt-4 text-gray-400 hover:bg-gray-700 hover:bg-opacity-25 hover:text-gray-100"> Chat Playground - - Text Playground + Reasoning Chat Playground + {/* + Text Playground + */} Image Playground diff --git a/frontend/components/reasoningChatPlayground/Assistant.jsx b/frontend/components/reasoningChatPlayground/Assistant.jsx new file mode 100644 index 00000000..c2d4674f --- /dev/null +++ b/frontend/components/reasoningChatPlayground/Assistant.jsx @@ -0,0 +1,28 @@ +"use client"; + +export default function Assistant({text, reasoning}) { + return ( +
+
+
+ ... +
+
+
{reasoning}
+
+
+
+
+ A +
+
+
{text}
+
+
+
+ ) +} \ No newline at end of file diff --git a/frontend/components/reasoningChatPlayground/Human.jsx b/frontend/components/reasoningChatPlayground/Human.jsx new file mode 100644 index 00000000..f627f38f --- /dev/null +++ b/frontend/components/reasoningChatPlayground/Human.jsx @@ -0,0 +1,32 @@ +"use client"; +import Image from 'next/image'; + +export default function Human({text, image}) { + return ( +
+
+
+ H +
+
+
{text}
+ {image && ( +
+ Attached image +
+ )} +
+
+
+ ) +} diff --git a/frontend/components/reasoningChatPlayground/Loader.jsx b/frontend/components/reasoningChatPlayground/Loader.jsx new file mode 100644 index 00000000..cbad9fde --- /dev/null +++ b/frontend/components/reasoningChatPlayground/Loader.jsx @@ -0,0 +1,27 @@ +"use client"; + +import React from "react"; + +export default function Loader() { + return ( +
+
+
+ A +
+
+
+
+
+
+
+
+ Loading... +
+
+
+
+ ); +}; \ No newline at end of file diff --git a/frontend/components/reasoningChatPlayground/ModelIndicator.jsx b/frontend/components/reasoningChatPlayground/ModelIndicator.jsx new file mode 100644 index 00000000..45334155 --- /dev/null +++ b/frontend/components/reasoningChatPlayground/ModelIndicator.jsx @@ -0,0 +1,14 @@ +"use client" + +export default function ModelIndicator({ modelName }) { + return ( +
+
+ +
+
+ ); +}; \ No newline at end of file diff --git a/frontend/components/reasoningChatPlayground/ReasoningChatComponent.jsx b/frontend/components/reasoningChatPlayground/ReasoningChatComponent.jsx new file mode 100644 index 00000000..85221ecb --- /dev/null +++ b/frontend/components/reasoningChatPlayground/ReasoningChatComponent.jsx @@ -0,0 +1,392 @@ +"use client"; + +import Human from "@/components/reasoningChatPlayground/Human"; +import React, { useState } from "react"; +import Assistant from "@/components/reasoningChatPlayground/Assistant"; +import Loader from "@/components/reasoningChatPlayground/Loader"; +import GlobalConfig from "@/app/app.config"; +import ReasoningModelSelector from "./ReasoningModelSelector"; +import { defaultModel } from "@/helpers/reasoningModelData"; +import NumericInput from "../NumericInput"; +import Image from 'next/image'; + + +export default function ChatContainer() { + const [conversation, setConversation] = useState([]); + const [history, setHistory] = useState([]); + const [inputValue, setInputValue] = useState(""); + const [isLoading, setIsLoading] = useState(false); + const [selectedModel, setSelectedModel] = useState(defaultModel); + const [maxTokens, setMaxTokens] = useState(defaultModel.maxTokenRange.default); + const [temperature, setTemperature] = useState(defaultModel.temperatureRange.default); + const [topP, setTopP] = useState(defaultModel.topPRange.default); + const [stopSequences, setStopSequences] = useState([]); + const [stopSequenceInput, setStopSequenceInput] = useState(''); + const [referenceImage, setReferenceImage] = useState(null); + const [previewImage, setPreviewImage] = useState('/placeholder.png'); + const fileInputRef = React.useRef(null); + + const endpoint = `/foundation-models/chat/${selectedModel.modelId}`; + const api = `${GlobalConfig.apiHost}:${GlobalConfig.apiPort}${endpoint}`; + + const handleInputChange = (e) => { + setInputValue(e.target.value); + }; + + const onModelChange = (newModel) => { + setSelectedModel(newModel); + clearChat() + } + + const handleMaxTokensChange = (value) => { + setMaxTokens(value); + }; + + const handleTemperatureChange = (value) => { + setTemperature(value); + }; + + const handleTopPChange = (value) => { + setTopP(value); + }; + + const handleStopSequenceInputChange = (e) => { + setStopSequenceInput(e.target.value); + }; + + const addStopSequence = () => { + if (stopSequenceInput.trim()) { + setStopSequences([...stopSequences, stopSequenceInput.trim()]); + setStopSequenceInput(''); + } + }; + + const removeStopSequence = (index) => { + setStopSequences(stopSequences.filter((_, i) => i !== index)); + }; + + const clearChat = () => { + setConversation([]); + setHistory([]); + }; + + const handleFileUpload = async (event) => { + const file = event.target.files[0]; + if (file) { + // Create preview for the UI + const reader = new FileReader(); + reader.onload = (e) => { + setPreviewImage(e.target.result); + }; + reader.readAsDataURL(file); + + // Compress and store the image + const compressedBase64 = await compressImage(file); + console.log('Compressed image size:', compressedBase64.length); + setReferenceImage(compressedBase64); + } + }; + + const compressImage = (file) => { + return new Promise((resolve) => { + const reader = new FileReader(); + reader.onload = (event) => { + const img = document.createElement('img'); // Use regular img element instead of Next.js Image + img.onload = () => { + const canvas = document.createElement('canvas'); + // Reduce max dimensions to 512x512 + const maxSize = 512; + let width = img.width; + let height = img.height; + + if (width > height) { + if (width > maxSize) { + height *= maxSize / width; + width = maxSize; + } + } else { + if (height > maxSize) { + width *= maxSize / height; + height = maxSize; + } + } + + canvas.width = width; + canvas.height = height; + + const ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0, width, height); + + // Increase compression by reducing quality to 0.5 (50%) + const compressedBase64 = canvas.toDataURL('image/jpeg', 0.5); + resolve(compressedBase64.split(',')[1]); + }; + img.src = event.target.result; + }; + reader.readAsDataURL(file); + }); + }; + + const sendMessage = async () => { + const currentImage = previewImage !== '/placeholder.png' ? previewImage : null; + const newMessage = { + sender: "Human", + message: inputValue, + image: currentImage + }; + setConversation(prevConversation => [...prevConversation, newMessage]); + setInputValue(''); + setReferenceImage(null); + setPreviewImage('/placeholder.png'); + + if (fileInputRef.current) { + fileInputRef.current.value = ''; + } + + try { + setIsLoading(true); + + const response = await fetch(api, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + prompt: inputValue, + history: history, + imageBytes: referenceImage, + maxTokens: parseInt(maxTokens, 10), + temperature: parseFloat(temperature), + topP: parseFloat(topP), + stopSequences: stopSequences, + enableReasoning: true, + maxReasoningTokens: 1200 + }) + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + await response.json().then(data => { + const reasoning = data.reasoningBlock != undefined ? data.reasoningBlock.reasoning : "No reasoning found"; + setConversation(prevConversation => [...prevConversation, { + sender: "Assistant", + message: data.textReply, + reasoning: reasoning + }]); + setHistory(data.history); + console.log(history) + }); + + } catch (error) { + console.error("Error sending message:", error); + } finally { + setIsLoading(false); + } + }; + + return
+

Reasoning Chat Playground

+
+ {/* model and parameter selection */} +
+
+ + +
+ +
+ {/* maxTokens */} +
+
+ +
+
+
+ +
+ {/* temperature */} +
+
+ +
+
+
+ +
+ {/* topP */} +
+
+ +
+
+
+ +
+ {/* Stop Sequences */} +
+
+ +
+
+
+ + +
+
+ {stopSequences.map((sequence, index) => ( +
+ {sequence} + +
+ ))} +
+ +
+
+ + {/* Conversation window */} +
+
+
+ {conversation.map((item, i) => item.sender === "Assistant" ? ( + + ) : ( + + ))} + {isLoading ? () : (
)} +
+
+
+ + {/* Input window */} +
+
+ {/* Text input */} +
+
+ { + if (event.key === 'Enter') { + sendMessage(); + } + }} + placeholder="Send a message" + className="flex w-full border rounded-xl focus:outline-none focus:border-indigo-300 pl-4 h-10" + /> +
+
+ {/* Reference image with preview */} +
+
+ +
+
+ Reference image +
+
+ + {/* Send button */} +
+ +
+ +
+
+
+
; +} \ No newline at end of file diff --git a/frontend/components/reasoningChatPlayground/ReasoningModelSelector.jsx b/frontend/components/reasoningChatPlayground/ReasoningModelSelector.jsx new file mode 100644 index 00000000..1dc873c3 --- /dev/null +++ b/frontend/components/reasoningChatPlayground/ReasoningModelSelector.jsx @@ -0,0 +1,49 @@ +"use client" +import React, {useState} from "react"; +import { models } from '../../helpers/reasoningModelData'; + +export default function ReasoningModelSelector({ model, onModelChange }) { + const [isOpen, setIsOpen] = useState(false); + + const toggleDropdown = () => { + setIsOpen(!isOpen); + }; + + const selectModel = (item) => { + setIsOpen(false); + onModelChange(item); + }; + + return ( +
+ +
+ ); +}; diff --git a/frontend/helpers/chatModelData.js b/frontend/helpers/chatModelData.js index e7a88816..b4911ac1 100644 --- a/frontend/helpers/chatModelData.js +++ b/frontend/helpers/chatModelData.js @@ -1,14 +1,313 @@ +export const defaultChatModel = { + modelName: "Amazon Nova Lite", + modelId: "amazon.nova-lite-v1:0", + temperatureRange: { + min: 0.0001, + max: 1, + default: 0.7 + }, + maxTokenRange: { + min: 0, + max: 5000, + default: 200 + }, + topPRange: { + default: 0.9, + min: 0, + max: 1 + }, + topKRange: { + min: 0, + max: null, + default: 50 + } +} -// TODO: check what models can be used in converse -// export const models = [ -// { -// modelId: "amazon.nova-canvas-v1:0", -// modelName: "Nova Canvas" -// }, -// { -// modelId: "amazon.titan-image-generator-v2:0", -// modelName: "Titan Image Generator" -// } -// ] +export const chatModels = [ + defaultModel, + // Antropic + { + modelName: "Athropic Claude 3 Haiku", + modelId: "anthropic.claude-3-haiku-20240307-v1:0", + topKRange: { + max: 500, + default: 0, + min: 0 + }, + temperatureRange: { + min: 0, + max: 1, + default: 1 + }, + supportedModality: AnthropicText, + topPRange: { + min: 0, + default: 0.999, + max: 1 + }, + maxTokenRange: { + min: 1, + default: 4096, + max: 4096 + } + }, + { + modelName: "Anthropic Claude Instant", + modelId: "anthropic.claude-instant-v1", + topPRange: { + max: 1, + min: 0, + default: 0.999 + }, + temperatureRange: { + default: 1, + max: 1, + min: 0 + }, + topKRange: { + min: 0, + max: 500, + default: 0 + }, + maxTokenRange: { + default: null, + min: 1, + max: null + } + }, + { + modelName: "Anthropic Claude", + modelId: "anthropic.claude-v2", + topPRange: { + min: 0, + max: 1, + default: 0.999 + }, + topKRange: { + max: 500, + default: 0, + min: 0 + }, + maxTokenRange: { + min: 1, + default: null, + max: null + }, + temperatureRange: { + min: 0, + max: 1, + default: 1 + } + }, + { + modelName: "Anthropic Claude 2.1", + modelId: "anthropic.claude-v2:1", + topPRange: { + min: 0, + max: 1, + default: 0.999 + }, + topKRange: { + max: 500, + default: 0, + min: 0 + }, + maxTokenRange: { + min: 1, + default: null, + max: null + }, + temperatureRange: { + min: 0, + max: 1, + default: 1 + } + }, + { + modelName: "Anthropic Claude 3.5 Haiku", + modelId: "us.anthropic.claude-3-5-haiku-20241022-v1:0", + temperatureRange: { + default: 1, + min: 0, + max: 1 + }, + maxTokenRange: { + max: 8192, + default: 8192, + min: 1 + }, + topKRange: { + default: 0, + min: 0, + max: 500 + }, + topPRange: { + max: 1, + default: 0.999, + min: 0 + }, + }, + // TODO: Opus and Sonnet 3.7 + // Amazon Nova + { + modelName: "Amazon Nova Micro", + modelId: "amazon.nova-micro-v1:0", + temperatureRange: { + min: 0.0001, + max: 1, + default: 0.7 + }, + maxTokenRange: { + min: 0, + max: 5000, + default: 200 + }, + topPRange: { + default: 0.9, + min: 0, + max: 1 + }, + topKRange: { + min: 0, + max: null, + default: 50 + } + }, + { + modelName: "Amazon Nova Pro", + modelId: "amazon.nova-pro-v1:0", + temperatureRange: { + min: 0.0001, + max: 1, + default: 0.7 + }, + maxTokenRange: { + min: 0, + max: 5000, + default: 200 + }, + topPRange: { + default: 0.9, + min: 0, + max: 1 + }, + topKRange: { + min: 0, + max: null, + default: 50 + } + }, + // Mistral + { + modelName: "Mistral Large (24.02)", + modelId: "mistral.mistral-large-2402-v1:0", + temperatureRange: { + min: 0, + max: 1, + default: 0.7 + }, + maxTokenRange: { + min: 0, + max: 8191, + default: 8191 + } + }, + { + modelName: "Mistral Small (24.02)", + modelId: "mistral.mistral-small-2402-v1:0", + temperatureRange: { + min: 0, + max: 1, + default: 0.7 + }, + maxTokenRange: { + min: 0, + max: 8191, + default: 8191 + } + }, + // Amazon Titan + { + modelName: "Amazon Titan Text Express", + modelId: "amazon.titan-text-express-v1", + temperatureRange: { + max: 1, + default: 0.7, + min: 0 + }, + maxTokenRange: { + max: 8192, + default: 512, + min: 0 + }, + topPRange: { + min: 0, + default: 0.9, + max: 1 + }, + }, + { + modelName: "Amazon Titan Text Premier", + modelId: "amazon.titan-text-premier-v1:0", + temperatureRange: { + min: 0, + max: 1, + default: 0.7 + }, + maxTokenRange: { + min: 0, + max: 3072, + default: 512 + }, + topPRange: { + max: 1, + default: 0.9, + min: 0 + } + }, + { + modelName: "Amazon Titan Text Lite", + modelId: "amazon.titan-text-lite-v1", + topPRange: { + max: 1, + default: 0.9, + min: 0 + }, + maxTokenRange: { + max: 4096, + min: 0, + default: 512 + }, + temperatureRange: { + default: 0.7, + max: 1, + min: 0 + } + }, + // DeepSeek + { + modelName: "Deep Seek", + modelId: "us.deepseek.r1-v1:0", + topPRange: { + max: 1, + default: 1, + min: 0 + }, + temperatureRange: { + default: 1, + min: 0, + max: 1 + }, + maxTokenRange: { + max: 32768, + default: 32768, + min: 1 + }, + }, +] -// export const defaultImageModel = models[0] +export const defaultPayload = { + prompt: "", + temperature: defaultModel.temperatureRange.default, + maxTokens: defaultModel.maxTokenRange.default +} \ No newline at end of file diff --git a/frontend/helpers/reasoningModelData.js b/frontend/helpers/reasoningModelData.js new file mode 100644 index 00000000..401d619f --- /dev/null +++ b/frontend/helpers/reasoningModelData.js @@ -0,0 +1,53 @@ +export const defaultModel = { + modelName: "Claude V3.7 Sonnet", + modelId: "us.anthropic.claude-3-7-sonnet-20250219-v1:0", + topKRange: { + max: 500, + default: 0, + min: 0 + }, + temperatureRange: { + min: 0, + max: 1, + default: 1 + }, + topPRange: { + min: 0, + default: 0.999, + max: 1 + }, + maxTokenRange: { + min: 1, + default: 8192, + max: 8192 + } +} + +export const models = [ + defaultModel, + // { + // modelName: "Deep Seek", + // modelId: "us.deepseek.r1-v1:0", + // topPRange: { + // max: 1, + // default: 1, + // min: 0 + // }, + // temperatureRange: { + // default: 1, + // min: 0, + // max: 1 + // }, + // maxTokenRange: { + // max: 32768, + // default: 32768, + // min: 1 + // }, + // }, +] + +export const defaultPayload = { + prompt: "", + temperature: defaultModel.temperatureRange.default, + maxTokens: defaultModel.maxTokenRange.default +} \ No newline at end of file From c556585dee5075e2636775156a80ec911a7dfbec Mon Sep 17 00:00:00 2001 From: monadierickx <126071495+monadierickx@users.noreply.github.com> Date: Tue, 13 May 2025 19:13:14 +0200 Subject: [PATCH 05/12] error handling --- backend/Package.swift | 2 +- .../PlaygroundAPI/Application+build.swift | 12 ++++++ .../chatPlayground/ChatComponent.jsx | 26 ++++++++++++- .../imagePlayground/ImageComponent.jsx | 24 +++++++++++- .../ImageVariationComponent.jsx | 24 +++++++++++- .../ReasoningChatComponent.jsx | 37 +++++++++++++++---- 6 files changed, 113 insertions(+), 12 deletions(-) diff --git a/backend/Package.swift b/backend/Package.swift index 18c5be79..2b861309 100644 --- a/backend/Package.swift +++ b/backend/Package.swift @@ -12,7 +12,7 @@ let package = Package( dependencies: [ .package(url: "https://github.com/hummingbird-project/hummingbird.git", from: "2.0.0"), .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.3.0"), - .package(url: "https://github.com/monadierickx/swift-bedrock-library.git", branch: "reasoning"), + .package(url: "https://github.com/monadierickx/swift-bedrock-library.git", branch: "error-handling"), ], targets: [ .executableTarget( diff --git a/backend/Sources/PlaygroundAPI/Application+build.swift b/backend/Sources/PlaygroundAPI/Application+build.swift index 9bdc86a9..3a2311cc 100644 --- a/backend/Sources/PlaygroundAPI/Application+build.swift +++ b/backend/Sources/PlaygroundAPI/Application+build.swift @@ -83,6 +83,17 @@ func buildRouter(useSSO: Bool, logger: Logger, profileName: String) async throws } let bedrock = try await BedrockService(authentication: auth) + // Error handling + @Sendable func handleBedrockServiceError(_ error: Error, context: String) throws { + if let bedrockServiceError = error as? BedrockServiceError { + logger.trace("BedrockServiceError while \(context)", metadata: ["error": "\(error)"]) + throw HTTPError(.badRequest, message: bedrockServiceError.message) + } else { + logger.trace("Error while \(context)", metadata: ["error": "\(error)"]) + throw HTTPError(.internalServerError, message: "Error: \(error)") + } + } + // List models // GET /foundation-models lists all models router.get("/foundation-models") { request, _ -> [ModelSummary] in @@ -227,6 +238,7 @@ func buildRouter(useSSO: Bool, logger: Logger, profileName: String) async throws "An error occured while generating chat", metadata: ["url": "/foundation-models/chat/:modelId", "error": "\(error)"] ) + try handleBedrockServiceError(error, context: "/foundation-models/chat/:modelId") throw HTTPError(.internalServerError, message: "Error: \(error)") } } diff --git a/frontend/components/chatPlayground/ChatComponent.jsx b/frontend/components/chatPlayground/ChatComponent.jsx index 90b3f9ce..d86d2c29 100644 --- a/frontend/components/chatPlayground/ChatComponent.jsx +++ b/frontend/components/chatPlayground/ChatComponent.jsx @@ -25,6 +25,7 @@ export default function ChatContainer() { const [referenceImage, setReferenceImage] = useState(null); const [previewImage, setPreviewImage] = useState('/placeholder.png'); const fileInputRef = React.useRef(null); + const [errorMessage, setErrorMessage] = useState(null); const endpoint = `/foundation-models/chat/${selectedModel.modelId}`; const api = `${GlobalConfig.apiHost}:${GlobalConfig.apiPort}${endpoint}`; @@ -145,7 +146,8 @@ export default function ChatContainer() { try { setIsLoading(true); - + setErrorMessage(null); + const response = await fetch(api, { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -161,7 +163,13 @@ export default function ChatContainer() { }); if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); + await response.json().then(data => { + console.log(data) + console.log(data.error.message) + let errorMsg = data.error.message + setErrorMessage(errorMsg); + throw new Error(errorMsg); + }); } await response.json().then(data => { @@ -292,6 +300,20 @@ export default function ChatContainer() { + {/* Error message display */} + {errorMessage && ( +
+ Error: + {errorMessage} + +
+ )} + {/* Conversation window */}
diff --git a/frontend/components/imagePlayground/ImageComponent.jsx b/frontend/components/imagePlayground/ImageComponent.jsx index 17e57547..2ed3f106 100644 --- a/frontend/components/imagePlayground/ImageComponent.jsx +++ b/frontend/components/imagePlayground/ImageComponent.jsx @@ -14,6 +14,7 @@ export default function ImageContainer() { const [isLoading, setIsLoading] = useState(false); const [selectedModel, setSelectedModel] = useState(defaultImageModel); const [nrOfImages, setNrOfImages] = useState(1); + const [errorMessage, setErrorMessage] = useState(null); const onModelChange = (newModel) => { @@ -40,6 +41,7 @@ export default function ImageContainer() { if (inputValue.trim() === '') { return; } setIsLoading(true); + setErrorMessage(null); // if (stylePreset === "no style") { // setStylePreset(""); @@ -59,7 +61,13 @@ export default function ImageContainer() { }); if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); + await response.json().then(data => { + console.log(data) + console.log(data.error.message) + let errorMsg = data.error.message + setErrorMessage(errorMsg); + throw new Error(errorMsg); + }); } const body = await response.json(); @@ -141,6 +149,20 @@ export default function ImageContainer() {
+ {/* Error message display */} + {errorMessage && ( +
+ Error: + {errorMessage} + +
+ )} + {/* images */}
diff --git a/frontend/components/imageVariationPlayground/ImageVariationComponent.jsx b/frontend/components/imageVariationPlayground/ImageVariationComponent.jsx index 2045b511..87f6bb4b 100644 --- a/frontend/components/imageVariationPlayground/ImageVariationComponent.jsx +++ b/frontend/components/imageVariationPlayground/ImageVariationComponent.jsx @@ -15,6 +15,7 @@ export default function ImageVariationContainer() { const [selectedModel, setSelectedModel] = useState(defaultImageModel); const [nrOfImages, setNrOfImages] = useState(1); const [similarity, setSimilarity] = useState(0.5); + const [errorMessage, setErrorMessage] = useState(null); const compressImage = (file) => { return new Promise((resolve) => { @@ -98,6 +99,7 @@ export default function ImageVariationContainer() { if (inputValue.trim() === '') { return; } setIsLoading(true); + setErrorMessage(null); const prompt = { prompt: inputValue.trim(), @@ -114,7 +116,13 @@ export default function ImageVariationContainer() { }); if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); + await response.json().then(data => { + console.log(data) + console.log(data.error.message) + let errorMsg = data.error.message + setErrorMessage(errorMsg); + throw new Error(errorMsg); + }); } const body = await response.json(); @@ -242,6 +250,20 @@ export default function ImageVariationContainer() { {/*
*/} + {/* Error message display */} + {errorMessage && ( +
+ Error: + {errorMessage} + +
+ )} + {/* images */}
diff --git a/frontend/components/reasoningChatPlayground/ReasoningChatComponent.jsx b/frontend/components/reasoningChatPlayground/ReasoningChatComponent.jsx index 85221ecb..db5fceea 100644 --- a/frontend/components/reasoningChatPlayground/ReasoningChatComponent.jsx +++ b/frontend/components/reasoningChatPlayground/ReasoningChatComponent.jsx @@ -25,6 +25,7 @@ export default function ChatContainer() { const [referenceImage, setReferenceImage] = useState(null); const [previewImage, setPreviewImage] = useState('/placeholder.png'); const fileInputRef = React.useRef(null); + const [errorMessage, setErrorMessage] = useState(null); const endpoint = `/foundation-models/chat/${selectedModel.modelId}`; const api = `${GlobalConfig.apiHost}:${GlobalConfig.apiPort}${endpoint}`; @@ -145,6 +146,7 @@ export default function ChatContainer() { try { setIsLoading(true); + setErrorMessage(null); const response = await fetch(api, { method: 'POST', @@ -158,12 +160,18 @@ export default function ChatContainer() { topP: parseFloat(topP), stopSequences: stopSequences, enableReasoning: true, - maxReasoningTokens: 1200 + maxReasoningTokens: 1200 // FIXME: add parmeter }) }); if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); + await response.json().then(data => { + console.log(data) + console.log(data.error.message) + let errorMsg = data.error.message + setErrorMessage(errorMsg); + throw new Error(errorMsg); + }); } await response.json().then(data => { @@ -178,7 +186,7 @@ export default function ChatContainer() { }); } catch (error) { - console.error("Error sending message:", error); + console.error("Error sending message:", error.message); } finally { setIsLoading(false); } @@ -213,10 +221,11 @@ export default function ChatContainer() { className="relative w-20" placeholder="1" value={maxTokens} - range={{ - min: defaultModel.maxTokenRange.min, - max: defaultModel.maxTokenRange.max, - default: defaultModel.maxTokenRange.default}} + range={{ + min: defaultModel.maxTokenRange.min, + max: defaultModel.maxTokenRange.max, + default: defaultModel.maxTokenRange.default + }} disabled={isLoading} callback={handleMaxTokensChange} /> @@ -300,6 +309,20 @@ export default function ChatContainer() {
+ {/* Error message display */} + {errorMessage && ( +
+ Error: + {errorMessage} + +
+ )} + {/* Conversation window */}
From 594bdc8c07774c1635aa4a3236f9a9a6fe5f4023 Mon Sep 17 00:00:00 2001 From: monadierickx <126071495+monadierickx@users.noreply.github.com> Date: Tue, 13 May 2025 19:22:53 +0200 Subject: [PATCH 06/12] formatting --- backend/Sources/PlaygroundAPI/Application+build.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/Sources/PlaygroundAPI/Application+build.swift b/backend/Sources/PlaygroundAPI/Application+build.swift index 3a2311cc..ca431313 100644 --- a/backend/Sources/PlaygroundAPI/Application+build.swift +++ b/backend/Sources/PlaygroundAPI/Application+build.swift @@ -230,7 +230,7 @@ func buildRouter(useSSO: Bool, logger: Logger, profileName: String) async throws } if let enableReasoning = input.enableReasoning, enableReasoning { builder = try builder.withReasoning() - .withMaxReasoningTokens(input.maxReasoningTokens) + .withMaxReasoningTokens(input.maxReasoningTokens) } return try await bedrock.converse(with: builder) } catch { From b401ca81a0fafe7f95879458d5d9450f414d679e Mon Sep 17 00:00:00 2001 From: monadierickx <126071495+monadierickx@users.noreply.github.com> Date: Wed, 14 May 2025 11:33:08 +0200 Subject: [PATCH 07/12] github actions --- .github/workflows/build_test_soundness.yml | 11 ++- .../chatPlayground/ChatComponent.jsx | 30 ++++---- .../ReasoningChatComponent.jsx | 71 +++++++++++++------ frontend/helpers/chatModelData.js | 38 +++++----- frontend/helpers/modelData.js | 28 ++++---- frontend/helpers/reasoningModelData.js | 5 ++ 6 files changed, 112 insertions(+), 71 deletions(-) diff --git a/.github/workflows/build_test_soundness.yml b/.github/workflows/build_test_soundness.yml index 3680cf7b..5dcedbcb 100644 --- a/.github/workflows/build_test_soundness.yml +++ b/.github/workflows/build_test_soundness.yml @@ -1,4 +1,4 @@ -name: Build And Test on EC2 +name: Build And Test on: [push, pull_request] @@ -17,6 +17,15 @@ jobs: - name: Build working-directory: backend run: swift build + + test: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Run tests + working-directory: backend + run: swift test # test: # runs-on: ubuntu-latest diff --git a/frontend/components/chatPlayground/ChatComponent.jsx b/frontend/components/chatPlayground/ChatComponent.jsx index d86d2c29..b81757ee 100644 --- a/frontend/components/chatPlayground/ChatComponent.jsx +++ b/frontend/components/chatPlayground/ChatComponent.jsx @@ -147,7 +147,7 @@ export default function ChatContainer() { try { setIsLoading(true); setErrorMessage(null); - + const response = await fetch(api, { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -202,6 +202,20 @@ export default function ChatContainer() {
+ {/* Error message display */} + {errorMessage && ( +
+ Error: + {errorMessage} + +
+ )} +
{/* maxTokens */}
@@ -300,20 +314,6 @@ export default function ChatContainer() {
- {/* Error message display */} - {errorMessage && ( -
- Error: - {errorMessage} - -
- )} - {/* Conversation window */}
diff --git a/frontend/components/reasoningChatPlayground/ReasoningChatComponent.jsx b/frontend/components/reasoningChatPlayground/ReasoningChatComponent.jsx index db5fceea..e86f92ef 100644 --- a/frontend/components/reasoningChatPlayground/ReasoningChatComponent.jsx +++ b/frontend/components/reasoningChatPlayground/ReasoningChatComponent.jsx @@ -18,8 +18,9 @@ export default function ChatContainer() { const [isLoading, setIsLoading] = useState(false); const [selectedModel, setSelectedModel] = useState(defaultModel); const [maxTokens, setMaxTokens] = useState(defaultModel.maxTokenRange.default); + const [maxReasoningTokens, setMaxReasoningTokens] = useState(defaultModel.maxReasoningTokensRange.default); const [temperature, setTemperature] = useState(defaultModel.temperatureRange.default); - const [topP, setTopP] = useState(defaultModel.topPRange.default); + // const [topP, setTopP] = useState(defaultModel.topPRange.default); const [stopSequences, setStopSequences] = useState([]); const [stopSequenceInput, setStopSequenceInput] = useState(''); const [referenceImage, setReferenceImage] = useState(null); @@ -43,13 +44,17 @@ export default function ChatContainer() { setMaxTokens(value); }; + const handleMaxReasoningTokensChange = (value) => { + setMaxReasoningTokens(value); + }; + const handleTemperatureChange = (value) => { setTemperature(value); }; - const handleTopPChange = (value) => { - setTopP(value); - }; + // const handleTopPChange = (value) => { + // setTopP(value); + // }; const handleStopSequenceInputChange = (e) => { setStopSequenceInput(e.target.value); @@ -157,10 +162,10 @@ export default function ChatContainer() { imageBytes: referenceImage, maxTokens: parseInt(maxTokens, 10), temperature: parseFloat(temperature), - topP: parseFloat(topP), + // topP: parseFloat(topP), stopSequences: stopSequences, enableReasoning: true, - maxReasoningTokens: 1200 // FIXME: add parmeter + maxReasoningTokens: parseInt(maxReasoningTokens, 10) }) }); @@ -207,6 +212,20 @@ export default function ChatContainer() {
+ {/* Error message display */} + {errorMessage && ( +
+ Error: + {errorMessage} + +
+ )} +
{/* maxTokens */}
@@ -230,6 +249,28 @@ export default function ChatContainer() { callback={handleMaxTokensChange} />
+ {/* maxReasoningTokens */} +
+
+ +
+
+
+ +
{/* temperature */}
@@ -249,7 +290,7 @@ export default function ChatContainer() { />
{/* topP */} -
+ {/*
+
*/} {/* Stop Sequences */}
@@ -309,20 +350,6 @@ export default function ChatContainer() {
- {/* Error message display */} - {errorMessage && ( -
- Error: - {errorMessage} - -
- )} - {/* Conversation window */}
diff --git a/frontend/helpers/chatModelData.js b/frontend/helpers/chatModelData.js index b4911ac1..a8736cb7 100644 --- a/frontend/helpers/chatModelData.js +++ b/frontend/helpers/chatModelData.js @@ -285,25 +285,25 @@ export const chatModels = [ } }, // DeepSeek - { - modelName: "Deep Seek", - modelId: "us.deepseek.r1-v1:0", - topPRange: { - max: 1, - default: 1, - min: 0 - }, - temperatureRange: { - default: 1, - min: 0, - max: 1 - }, - maxTokenRange: { - max: 32768, - default: 32768, - min: 1 - }, - }, + // { + // modelName: "Deep Seek", + // modelId: "us.deepseek.r1-v1:0", + // topPRange: { + // max: 1, + // default: 1, + // min: 0 + // }, + // temperatureRange: { + // default: 1, + // min: 0, + // max: 1 + // }, + // maxTokenRange: { + // max: 32768, + // default: 32768, + // min: 1 + // }, + // }, ] export const defaultPayload = { diff --git a/frontend/helpers/modelData.js b/frontend/helpers/modelData.js index 48594f97..f1396018 100644 --- a/frontend/helpers/modelData.js +++ b/frontend/helpers/modelData.js @@ -171,20 +171,20 @@ export const models = [ default: 200 } }, - { - modelName: "Deep Seek", - modelId: "us.deepseek.r1-v1:0", - temperatureRange: { - min: 0, - max: 1, - default: 0.5 - }, - maxTokenRange: { - min: 0, - max: 8191, - default: 200 - } - }, + // { + // modelName: "Deep Seek", + // modelId: "us.deepseek.r1-v1:0", + // temperatureRange: { + // min: 0, + // max: 1, + // default: 0.5 + // }, + // maxTokenRange: { + // min: 0, + // max: 8191, + // default: 200 + // } + // }, ] export const defaultPayload = { diff --git a/frontend/helpers/reasoningModelData.js b/frontend/helpers/reasoningModelData.js index 401d619f..f2f03ccd 100644 --- a/frontend/helpers/reasoningModelData.js +++ b/frontend/helpers/reasoningModelData.js @@ -20,6 +20,11 @@ export const defaultModel = { min: 1, default: 8192, max: 8192 + }, + maxReasoningTokensRange: { + min: 1024, + default: 4096, + max: 8191 } } From 22030e375eaadd6e21b1c101c2c2de4a90414dd8 Mon Sep 17 00:00:00 2001 From: monadierickx <126071495+monadierickx@users.noreply.github.com> Date: Wed, 14 May 2025 11:34:44 +0200 Subject: [PATCH 08/12] yamllint --- .github/workflows/build_test_soundness.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_test_soundness.yml b/.github/workflows/build_test_soundness.yml index 5dcedbcb..6fd2ebe9 100644 --- a/.github/workflows/build_test_soundness.yml +++ b/.github/workflows/build_test_soundness.yml @@ -17,7 +17,7 @@ jobs: - name: Build working-directory: backend run: swift build - + test: runs-on: ubuntu-latest steps: From 31268eee7687eaa2e5f4f2c6d4e0583b736d0117 Mon Sep 17 00:00:00 2001 From: monadierickx <126071495+monadierickx@users.noreply.github.com> Date: Wed, 14 May 2025 11:45:23 +0200 Subject: [PATCH 09/12] actions --- ...test_soundness.yml => build_soundness.yml} | 41 ++++++------------- 1 file changed, 13 insertions(+), 28 deletions(-) rename .github/workflows/{build_test_soundness.yml => build_soundness.yml} (68%) diff --git a/.github/workflows/build_test_soundness.yml b/.github/workflows/build_soundness.yml similarity index 68% rename from .github/workflows/build_test_soundness.yml rename to .github/workflows/build_soundness.yml index 6fd2ebe9..53867d11 100644 --- a/.github/workflows/build_test_soundness.yml +++ b/.github/workflows/build_soundness.yml @@ -1,33 +1,9 @@ -name: Build And Test +name: Build And Soundness checks on: [push, pull_request] jobs: - build: - runs-on: ubuntu-latest - container: swift:6.0.3-amazonlinux2 - - steps: - # GitHub checkout action has a dep on NodeJS 20 which is not running on Amazonlinux2 - # workaround is to manually checkout the repository - # https://github.com/actions/checkout/issues/1487 - - name: Manually Clone repository - run: | - git clone https://github.com/${{ github.repository }} . - - name: Build - working-directory: backend - run: swift build - - test: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - name: Run tests - working-directory: backend - run: swift test - - # test: + # build: # runs-on: ubuntu-latest # container: swift:6.0.3-amazonlinux2 @@ -38,9 +14,18 @@ jobs: # - name: Manually Clone repository # run: | # git clone https://github.com/${{ github.repository }} . - # - name: Run tests + # - name: Build # working-directory: backend - # run: swift test + # run: swift build + + build: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Run tests + working-directory: backend + run: swift build soundness: name: Soundness From a42fad3e2fcab52889777c6e45ab433db67c74d5 Mon Sep 17 00:00:00 2001 From: monadierickx <126071495+monadierickx@users.noreply.github.com> Date: Wed, 14 May 2025 11:52:18 +0200 Subject: [PATCH 10/12] actions --- .github/workflows/build_soundness.yml | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/.github/workflows/build_soundness.yml b/.github/workflows/build_soundness.yml index 53867d11..e4c6e1db 100644 --- a/.github/workflows/build_soundness.yml +++ b/.github/workflows/build_soundness.yml @@ -3,21 +3,6 @@ name: Build And Soundness checks on: [push, pull_request] jobs: - # build: - # runs-on: ubuntu-latest - # container: swift:6.0.3-amazonlinux2 - - # steps: - # # GitHub checkout action has a dep on NodeJS 20 which is not running on Amazonlinux2 - # # workaround is to manually checkout the repository - # # https://github.com/actions/checkout/issues/1487 - # - name: Manually Clone repository - # run: | - # git clone https://github.com/${{ github.repository }} . - # - name: Build - # working-directory: backend - # run: swift build - build: runs-on: ubuntu-latest steps: From 0ca9a6cc31215c908980723aa6eb3092b7ef1432 Mon Sep 17 00:00:00 2001 From: monadierickx <126071495+monadierickx@users.noreply.github.com> Date: Wed, 14 May 2025 15:48:07 +0200 Subject: [PATCH 11/12] dependencies updated --- backend/Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/Package.swift b/backend/Package.swift index 2b861309..74015ef1 100644 --- a/backend/Package.swift +++ b/backend/Package.swift @@ -12,7 +12,7 @@ let package = Package( dependencies: [ .package(url: "https://github.com/hummingbird-project/hummingbird.git", from: "2.0.0"), .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.3.0"), - .package(url: "https://github.com/monadierickx/swift-bedrock-library.git", branch: "error-handling"), + .package(url: "git@github.com:sebsto/swift-bedrock-library.git", branch: "main"), ], targets: [ .executableTarget( From 8ce37fe31b6006fd45b80420f7917a566cf3f4ce Mon Sep 17 00:00:00 2001 From: monadierickx <126071495+monadierickx@users.noreply.github.com> Date: Wed, 14 May 2025 16:14:04 +0200 Subject: [PATCH 12/12] actions --- backend/Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/Package.swift b/backend/Package.swift index 74015ef1..99c425da 100644 --- a/backend/Package.swift +++ b/backend/Package.swift @@ -12,7 +12,7 @@ let package = Package( dependencies: [ .package(url: "https://github.com/hummingbird-project/hummingbird.git", from: "2.0.0"), .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.3.0"), - .package(url: "git@github.com:sebsto/swift-bedrock-library.git", branch: "main"), + .package(url: "https://github.com/sebsto/swift-bedrock-library.git", branch: "main"), ], targets: [ .executableTarget(