Skip to content

Conversation

@RedwindA
Copy link
Contributor

@RedwindA RedwindA commented Oct 11, 2025

PR 类型

  • Bug 修复
  • 新功能
  • 文档更新
  • 其他

PR 是否包含破坏性更新?

PR 描述

修复目的

修复 issue #1990 中报告的模型名称大小写敏感性问题。之前在MySQL 数据库中,deepseek-ai/DeepSeek-V3.1-Terminusdeepseek-ai/deepseek-v3.1-terminus被视为相同的模型名称,导致无法为不同大小写的模型名称配置不同的渠道(例如硅基流动使用大写版本,英伟达使用小写版本)。

实现细节

  1. 数据库模式更新

    • Model 结构体的 ModelName 字段添加collation:utf8mb4_bin 标签,使 MySQL使用区分大小写的排序规则
    • Ability 结构体的 Model 字段添加相同的排序规则,确保能力表中的模型匹配也区分大小写
  2. 查询逻辑优化

    • 修改 IsModelNameDuplicated() 函数,对 MySQL 使用BINARY 关键字进行大小写敏感的比较
    • PostgreSQL 和 SQLite默认已经是大小写敏感的,无需特殊处理
  3. 自动迁移支持

    • 新增 fixModelNameCollation()迁移函数,在系统启动时自动检测并更新现有 MySQL数据库的字段排序规则
    • 迁移函数会检查当前排序规则,仅在必要时执行 ALTER TABLE 操作
    • 对不存在的表会优雅地忽略错误,不影响新安装

影响范围

  • 新安装:数据库表将自动使用大小写敏感的排序规则
  • 现有安装:首次启动时会自动执行迁移,将models.model_nameabilities.model字段更新为大小写敏感
  • 用户现在可以创建和管理大小写不同但其他字符相同的模型,每个模型可以独立绑定渠道

测试
图片

Summary by CodeRabbit

  • New Features

    • None
  • Bug Fixes

    • Prevents duplicate model names that differ only by letter case by enforcing case-sensitive checks in MySQL environments.
    • Improves reliability of database migrations by automatically correcting column collations when needed.
  • Chores

    • Adds migration step to align database collation with expected behavior, with non-blocking warnings if adjustments fail.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 11, 2025

Walkthrough

Adds a MySQL-specific collation-fix step to migrations to set certain columns to utf8mb4_bin when needed, and updates the model-name duplicate check to use a case-sensitive comparison on MySQL while retaining previous behavior for other databases.

Changes

Cohort / File(s) Summary
Migration collation enforcement
model/main.go
Adds fixModelNameCollation to detect and convert models.model_name and abilities.model columns to utf8mb4_bin when non-binary; calls it after AutoMigrate in migrateDB (including LOG_DB) and logs non-fatal warnings on failure.
Case-sensitive duplicate checks (MySQL)
model/model_meta.go
Modifies IsModelNameDuplicated to use a BINARY (case-sensitive / utf8mb4_bin) comparison when common.UsingMySQL is true, otherwise uses the previous equality check; preserves return contract (cnt > 0, err).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor App
  participant Migrator as migrateDB
  participant ORM as AutoMigrate
  participant Collation as fixModelNameCollation
  participant MySQL as DB

  App->>Migrator: Initialize / migrate
  Migrator->>ORM: AutoMigrate(models)
  ORM-->>Migrator: Done
  Migrator->>Collation: fixModelNameCollation()
  Collation->>MySQL: Query current collations (models, abilities)
  alt Non-binary collation detected
    Collation->>MySQL: ALTER TABLE ... MODIFY COLUMN ... utf8mb4_bin
    MySQL-->>Collation: OK / Err
  else Already binary or table/column missing
    Collation-->>Migrator: No-op / skipped
  end
  Collation-->>Migrator: Log outcome (warn if failed)
  Migrator-->>App: Continue
Loading
sequenceDiagram
  autonumber
  actor Caller
  participant Meta as IsModelNameDuplicated
  participant DB as Database

  Caller->>Meta: Check duplicate(model_name)
  alt Using MySQL
    Meta->>DB: SELECT COUNT(*) WHERE BINARY model_name = ?
  else Other DB
    Meta->>DB: SELECT COUNT(*) WHERE model_name = ?
  end
  DB-->>Meta: cnt, err
  Meta-->>Caller: (cnt > 0), err
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I nudge the schema, ears held high,
Collations crisp beneath the sky.
I sniff for duplicates, case by case,
In MySQL burrows I tidy the space.
A hop, a log, migrations win—utf8mb4_bin. 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly describes the core change—enforcing case-sensitive model name matching—and highlights its purpose of supporting multiple channels distinguished by case variants without introducing unrelated details or generic language.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
model/main.go (1)

261-261: Consider using suffix check for more precise collation detection.

The current check uses strings.Contains(strings.ToLower(collation), "_bin") which could theoretically match unexpected patterns. While MySQL collations conventionally use _bin as a suffix, using strings.HasSuffix would be more precise.

Apply this diff for more precise matching:

-	} else if !strings.Contains(strings.ToLower(modelCollation), "_bin") {
+	} else if !strings.HasSuffix(strings.ToLower(modelCollation), "_bin") {

And similarly for line 276:

-	} else if !strings.Contains(strings.ToLower(abilityCollation), "_bin") {
+	} else if !strings.HasSuffix(strings.ToLower(abilityCollation), "_bin") {

Also applies to: 276-276

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 77f8e51 and 4d6087d.

📒 Files selected for processing (2)
  • model/main.go (2 hunks)
  • model/model_meta.go (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
model/model_meta.go (2)
common/database.go (1)
  • UsingMySQL (12-12)
model/main.go (1)
  • DB (63-63)
model/main.go (2)
common/database.go (1)
  • UsingMySQL (12-12)
common/sys_log.go (1)
  • SysLog (11-14)
🔇 Additional comments (6)
model/model_meta.go (2)

24-24: Verify that the collation tag is present.

The PR description states that a collation:utf8mb4_bin tag should be added to the ModelName field, but it's not visible in the provided code. This tag is essential for ensuring new installations create tables with case-sensitive collation by default.

Please verify that the struct definition includes the collation tag:

ModelName string `json:"model_name" gorm:"size:128;not null;collation:utf8mb4_bin;uniqueIndex:uk_model_name_delete_at,priority:1"`

57-63: LGTM! The conditional case-sensitive comparison is correctly implemented.

The use of the BINARY keyword for MySQL ensures case-sensitive matching, while PostgreSQL and SQLite maintain their default case-sensitive behavior. The error handling is appropriate.

model/main.go (4)

312-317: Consider whether migration failures should be non-fatal.

The migration logs warnings but continues on error (line 315-316). While this maintains backwards compatibility, it means installations with migration failures will continue to have case-insensitive collations, potentially causing the original issue (#1990) to persist.

Please verify this is the intended behavior. If the collation fix is critical for correctness, consider:

  1. Making the error fatal for new installations (checking if tables are empty)
  2. Adding a system health check that warns admins of misconfigured collations
  3. Documenting the manual fix procedure for failed migrations

249-286: LGTM on the overall migration approach.

The function correctly:

  • Checks if MySQL is in use before proceeding
  • Queries current collations from information_schema
  • Handles missing tables gracefully
  • Uses safe SQL with hardcoded identifiers (no injection risk)
  • Applies utf8mb4_bin collation for case-sensitive comparison

The approach of checking and conditionally updating is good for backwards compatibility.


322-374: Remove collation‐fix suggestion: migrateDBFast isn’t invoked anywhere, so adding fixModelNameCollation here has no effect.

Likely an incorrect or invalid review comment.


249-286: No mismatch in abilities.model column size
The ALTER TABLE uses VARCHAR(255), which matches the Ability.Model gorm tag.

- Add case-sensitive collation (utf8mb4_bin) to model_name and ability.model columns
- Update IsModelNameDuplicated to use BINARY comparison for MySQL
- Add automatic migration to update existing MySQL databases
- PostgreSQL and SQLite remain case-sensitive by default

Fixes QuantumNous#1990
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
model/main.go (1)

255-283: Handle "no result" cases before issuing ALTER

Line 263: when the information_schema query finds no matching row (table or column absent), Scan leaves modelCollation empty but still falls through to the ALTER, which then fails with Table 'models' doesn't exist. The same pattern appears around Line 278. That produces a warning every startup on environments where those tables are legitimately absent (despite the intent stated in the comment) and the collation upgrade never runs. Please detect the “no result” condition explicitly—e.g., scan into sql.NullString or use Row().Scan and skip when err == sql.ErrNoRows—before attempting the ALTER so we truly “ignore missing tables.”

+	var modelCollation sql.NullString
-	err := DB.Raw("SELECT COLLATION_NAME ...").Scan(&modelCollation).Error
-	if err != nil {
-		// Table might not exist yet, ignore error
-		common.SysLog(...)
-	} else if !strings.HasSuffix(strings.ToLower(modelCollation), "_bin") {
+	row := DB.Raw("SELECT COLLATION_NAME ...").Row()
+	switch err := row.Scan(&modelCollation); err {
+	case nil:
+		if modelCollation.Valid && !strings.HasSuffix(strings.ToLower(modelCollation.String), "_bin") {
 			...
 		}
+	case sql.ErrNoRows:
+		// nothing to migrate for this column
+	default:
+		common.SysLog(...)
+	}

Repeat the same pattern for the abilities.model block.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4d6087d and da8a5b7.

📒 Files selected for processing (2)
  • model/main.go (2 hunks)
  • model/model_meta.go (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
model/main.go (2)
common/database.go (1)
  • UsingMySQL (12-12)
common/sys_log.go (1)
  • SysLog (11-14)
model/model_meta.go (2)
common/database.go (1)
  • UsingMySQL (12-12)
model/main.go (1)
  • DB (63-63)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant