Explorar el Código

新增一个主体和场景名称替换为强制列表中的名称的激进策略代码,暂不启用

lh hace 1 mes
padre
commit
906f2d7a81
Se han modificado 1 ficheros con 187 adiciones y 0 borrados
  1. 187 0
      app/Services/DeepSeek/DeepSeekService.php

+ 187 - 0
app/Services/DeepSeek/DeepSeekService.php

@@ -8233,6 +8233,12 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         $episode_arr = handleEpisodeContentForAce($fullContent);
         logDB('deepseek', 'info', '解析内容', $episode_arr);
 
+        // // 如果有anime_script_id,进行主体和场景名称的智能匹配和替换(激进策略)
+        // if ($anime_script_id && !empty($extra_roles) && !empty($extra_scenes)) {
+        //     $episode_arr = $this->matchAndReplaceRolesAndScenes($episode_arr, $extra_roles, $extra_scenes);
+        //     logDB('deepseek', 'info', '匹配替换后的解析内容', $episode_arr);
+        // }
+
         // 验证逻辑:如果anime_script_id有值,需要验证生成的主体和场景是否匹配
         $max_retries = 3;
         $retry_count = 0;
@@ -8353,6 +8359,12 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
                 // 重新解析内容
                 dLog('deepseek')->info("第{$retry_count}次重试完整内容: " . $fullContent);
                 $episode_arr = handleEpisodeContentForAce($fullContent);
+                
+                // // 进行主体和场景名称的智能匹配和替换(激进策略)
+                // if ($anime_script_id && !empty($extra_roles) && !empty($extra_scenes)) {
+                //     $episode_arr = $this->matchAndReplaceRolesAndScenes($episode_arr, $extra_roles, $extra_scenes);
+                // }
+                
                 logDB('deepseek', 'info', "第{$retry_count}次重试解析内容", $episode_arr);
 
                 // 重新验证
@@ -8568,6 +8580,181 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
     }
 
     /**
+     * 智能匹配并替换主体和场景名称
+     * 如果生成的主体或场景名称是强制设定名称的子串,则自动替换为完整名称
+     * 
+     * @param array $episode_arr 解析后的剧集数据
+     * @param array $extra_roles 强制主体设定(key为主体名称)
+     * @param array $extra_scenes 强制场景设定(key为场景名称)
+     * @return array 替换后的剧集数据
+     */
+    private function matchAndReplaceRolesAndScenes($episode_arr, $extra_roles, $extra_scenes) {
+        $replaced_count = 0;
+        
+        // 1. 处理主体列表
+        if (!empty($episode_arr['roles'])) {
+            foreach ($episode_arr['roles'] as &$role) {
+                $generated_role_name = $role['role'] ?? '';
+                
+                // 跳过旁白
+                if ($generated_role_name === '旁白') {
+                    continue;
+                }
+                
+                // 如果生成的主体名不在强制设定中,尝试模糊匹配
+                if (!isset($extra_roles[$generated_role_name])) {
+                    $matched_role = $this->findMatchingName($generated_role_name, array_keys($extra_roles));
+                    
+                    if ($matched_role) {
+                        dLog('deepseek')->info("主体名称替换: {$generated_role_name} => {$matched_role}");
+                        $role['role'] = $matched_role;
+                        $replaced_count++;
+                    }
+                }
+            }
+        }
+        
+        // 2. 处理场景列表
+        if (!empty($episode_arr['scenes'])) {
+            foreach ($episode_arr['scenes'] as &$scene) {
+                $generated_scene_name = $scene['scene'] ?? '';
+                
+                // 如果生成的场景名不在强制设定中,尝试模糊匹配
+                if (!isset($extra_scenes[$generated_scene_name])) {
+                    $matched_scene = $this->findMatchingName($generated_scene_name, array_keys($extra_scenes));
+                    
+                    if ($matched_scene) {
+                        dLog('deepseek')->info("场景名称替换: {$generated_scene_name} => {$matched_scene}");
+                        $scene['scene'] = $matched_scene;
+                        $replaced_count++;
+                    }
+                }
+            }
+        }
+        
+        // 3. 处理分段剧本中的主体和场景引用(全能模式下只使用segment_content字段)
+        if (!empty($episode_arr['acts'])) {
+            foreach ($episode_arr['acts'] as &$act) {
+                if (!empty($act['segments'])) {
+                    foreach ($act['segments'] as &$segment) {
+                        if (!empty($segment['segment_content'])) {
+                            $original_content = $segment['segment_content'];
+                            $replaced_content = $original_content;
+                            
+                            // 替换场景名 - 在文本中查找并替换
+                            foreach (array_keys($extra_scenes) as $full_scene_name) {
+                                // 尝试找到可能的短名称
+                                $potential_short_names = [];
+                                
+                                // 提取场景名的主要部分(冒号之前)
+                                if (mb_strpos($full_scene_name, ':') !== false) {
+                                    $short_name = mb_substr($full_scene_name, 0, mb_strpos($full_scene_name, ':'));
+                                    $potential_short_names[] = $short_name;
+                                } elseif (mb_strpos($full_scene_name, ':') !== false) {
+                                    $short_name = mb_substr($full_scene_name, 0, mb_strpos($full_scene_name, ':'));
+                                    $potential_short_names[] = $short_name;
+                                }
+                                
+                                // 替换场景字段中的短名称
+                                foreach ($potential_short_names as $short_name) {
+                                    if ($short_name !== $full_scene_name) {
+                                        $pattern = '/(?<=场景:|场景:|拍摄场景:|拍摄场景:|背景场景:|背景场景:|环境:|环境:)' . preg_quote($short_name, '/') . '(?=\s|$|\n)/u';
+                                        $new_content = preg_replace($pattern, $full_scene_name, $replaced_content);
+                                        if ($new_content !== $replaced_content) {
+                                            $replaced_content = $new_content;
+                                            $replaced_count++;
+                                            dLog('deepseek')->info("场景名替换: {$short_name} => {$full_scene_name}");
+                                        }
+                                    }
+                                }
+                            }
+                            
+                            // 替换配音角色名(跳过旁白)
+                            foreach (array_keys($extra_roles) as $full_role_name) {
+                                if ($full_role_name === '旁白') {
+                                    continue;
+                                }
+                                
+                                // 尝试找到可能的短名称
+                                $potential_short_names = [];
+                                
+                                // 提取角色名的主要部分(短横线之前)
+                                if (mb_strpos($full_role_name, '-') !== false) {
+                                    $short_name = mb_substr($full_role_name, 0, mb_strpos($full_role_name, '-'));
+                                    $potential_short_names[] = $short_name;
+                                }
+                                
+                                // 替换配音台词中的短名称
+                                foreach ($potential_short_names as $short_name) {
+                                    if ($short_name !== $full_role_name) {
+                                        $pattern = '/(?<=配音台词:\[|配音台词:\[|中文配音:\[|中文配音:\[)\s*' . preg_quote($short_name, '/') . '\s*(?=\])/u';
+                                        $new_content = preg_replace($pattern, $full_role_name, $replaced_content);
+                                        if ($new_content !== $replaced_content) {
+                                            $replaced_content = $new_content;
+                                            $replaced_count++;
+                                            dLog('deepseek')->info("角色名替换: {$short_name} => {$full_role_name}");
+                                        }
+                                    }
+                                }
+                            }
+                            
+                            // 如果有替换,更新segment_content
+                            if ($replaced_content !== $original_content) {
+                                $segment['segment_content'] = $replaced_content;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        
+        if ($replaced_count > 0) {
+            logDB('deepseek', 'info', '主体和场景名称智能替换', [
+                'replaced_count' => $replaced_count
+            ]);
+        }
+        
+        return $episode_arr;
+    }
+
+    /**
+     * 查找匹配的名称
+     * 规则:如果生成的名称是强制设定名称的子串(开头部分),则返回匹配的强制设定名称
+     * 
+     * @param string $generated_name 生成的名称
+     * @param array $expected_names 预期的名称列表
+     * @return string|null 匹配到的名称,如果没有匹配则返回null
+     */
+    private function findMatchingName($generated_name, $expected_names) {
+        if (empty($generated_name)) {
+            return null;
+        }
+        
+        // 尝试精确匹配
+        if (in_array($generated_name, $expected_names)) {
+            return $generated_name;
+        }
+        
+        // 尝试模糊匹配:生成的名称是否为某个预期名称的开头部分
+        foreach ($expected_names as $expected_name) {
+            // 检查生成的名称是否是预期名称的开头(如"沈秋岚"是"沈秋岚-程家居家围裙造型"的开头)
+            if (mb_strpos($expected_name, $generated_name) === 0) {
+                return $expected_name;
+            }
+        }
+        
+        // 更宽松的匹配:检查生成的名称是否包含在预期名称中的任意位置
+        // 这样可以处理一些变体,但优先级较低
+        foreach ($expected_names as $expected_name) {
+            if (mb_strpos($expected_name, $generated_name) !== false) {
+                return $expected_name;
+            }
+        }
+        
+        return null;
+    }
+
+    /**
      * 重新生成分段剧本
      * @param array $data 包含以下字段:
      *   - prompt: string|null 用户修改要求(可选)