Parcourir la source

feat: add costly model to FakeChatService

Added a new 'costly' model to FakeChatService that simulates incurring costs similar to real AI services. This model can be used for testing cost tracking without incurring actual external API costs.

ai: true
KernelDeimos il y a 1 mois
Parent
commit
42c6f92048
1 fichiers modifiés avec 108 ajouts et 21 suppressions
  1. 108 21
      src/backend/src/modules/puterai/FakeChatService.js

+ 108 - 21
src/backend/src/modules/puterai/FakeChatService.js

@@ -34,6 +34,41 @@ class FakeChatService extends BaseService {
     }
     static IMPLEMENTS = {
         ['puter-chat-completion']: {
+            /**
+            * Returns a list of available models with their details
+            * @returns {Promise<Object[]>} Array of model details including costs
+            * @description Returns detailed information about available models including
+            * their costs for input and output tokens
+            */
+            async models () {
+                return [
+                    {
+                        id: 'fake',
+                        aliases: [],
+                        cost: {
+                            input: 0,
+                            output: 0
+                        }
+                    },
+                    {
+                        id: 'costly',
+                        aliases: [],
+                        cost: {
+                            input: 1000,  // 1000 microcents per million tokens (0.001 cents per 1000 tokens)
+                            output: 2000  // 2000 microcents per million tokens (0.002 cents per 1000 tokens)
+                        }
+                    },
+                    {
+                        id: 'abuse',
+                        aliases: [],
+                        cost: {
+                            input: 0,
+                            output: 0
+                        }
+                    }
+                ];
+            },
+            
             /**
             * Returns a list of available model names including their aliases
             * @returns {Promise<string[]>} Array of model identifiers and their aliases
@@ -41,15 +76,15 @@ class FakeChatService extends BaseService {
             * flattening them into a single array of strings that can be used for model selection
             */
             async list () {
-                return ['fake'];
+                return ['fake', 'costly', 'abuse'];
             },
 
             /**
             * Simulates a chat completion request by generating random Lorem Ipsum text
             * @param {Object} params - The completion parameters
-            * @param {Array} params.messages - Array of chat messages (unused in fake implementation)
+            * @param {Array} params.messages - Array of chat messages
             * @param {boolean} params.stream - Whether to stream the response (unused in fake implementation)
-            * @param {string} params.model - The model to use (unused in fake implementation)
+            * @param {string} params.model - The model to use ('fake', 'costly', or 'abuse')
             * @returns {Object} A simulated chat completion response with Lorem Ipsum content
             */
             async complete ({ messages, stream, model }) {
@@ -64,38 +99,90 @@ class FakeChatService extends BaseService {
                         min: 12
                     },
                 });
+                
+                // Determine token counts based on messages and model
+                const usedModel = model || this.get_default_model();
+                
+                // For the costly model, simulate actual token counting
+                let inputTokens = 0;
+                let outputTokens = 0;
+                
+                if (usedModel === 'costly') {
+                    // Simple token estimation: roughly 4 chars per token for input
+                    if (messages && messages.length > 0) {
+                        for (const message of messages) {
+                            if (typeof message.content === 'string') {
+                                inputTokens += Math.ceil(message.content.length / 4);
+                            } else if (Array.isArray(message.content)) {
+                                for (const content of message.content) {
+                                    if (content.type === 'text') {
+                                        inputTokens += Math.ceil(content.text.length / 4);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    
+                    // Generate random output token count between 50 and 200
+                    outputTokens = Math.floor(Math.random() * 150) + 50;
+                }
+                
+                // Generate the response text
+                let responseText;
+                if (usedModel === 'abuse') {
+                    responseText = dedent(`
+                        This is a message from ${
+                            this.global_config.origin}. We have detected abuse of our services.
+                        
+                        If you are seeing this on another website, please report it to ${
+                            this.global_config.abuse_email ?? 'hi@puter.com'}
+                    `);
+                } else {
+                    // Generate 1-3 paragraphs for both fake and costly models
+                    responseText = li.generateParagraphs(
+                        Math.floor(Math.random() * 3) + 1
+                    );
+                }
+                
+                // Report usage based on model
+                const usage = {
+                    "input_tokens": usedModel === 'costly' ? inputTokens : 0,
+                    "output_tokens": usedModel === 'costly' ? outputTokens : 1
+                };
+                
+                // Emit an event to report usage for the costly model
+                if (usedModel === 'costly') {
+                    try {
+                        const svc_event = this.services.get('event');
+                        svc_event.emit('ai.prompt.report-usage', {
+                            actor: this.context?.actor,
+                            service_used: 'fake-chat',
+                            model_used: 'costly',
+                            usage: usage
+                        });
+                    } catch (error) {
+                        this.log.error('Failed to report usage', error);
+                    }
+                }
+                
                 return {
                     "index": 0,
                     message: {
                         "id": "00000000-0000-0000-0000-000000000000",
                         "type": "message",
                         "role": "assistant",
-                        "model": "fake",
+                        "model": usedModel,
                         "content": [
                             {
                                 "type": "text",
-                                "text": model === 'abuse' ? dedent(`
-                                        This is a message from ${
-                                            this.global_config.origin}. We have detected abuse of our services.
-                                        
-                                        If you are seeing this on another website, please report it to ${
-                                            this.global_config.abuse_email ?? 'hi@puter.com'}
-                                    `) : li.generateParagraphs(
-                                    Math.floor(Math.random() * 3) + 1
-                                )
+                                "text": responseText
                             }
                         ],
                         "stop_reason": "end_turn",
                         "stop_sequence": null,
-                        "usage": {
-                            "input_tokens": 0,
-                            "output_tokens": 1
-                        }
-                    },
-                    "usage": {
-                        "input_tokens": 0,
-                        "output_tokens": 1
+                        "usage": usage
                     },
+                    "usage": usage,
                     "logprobs": null,
                     "finish_reason": "stop"
                 }