# 05.1 AI的局限与幻觉

## 核心问题

> AI在空间分析中哪些地方可能出错？
> 当AI给出一个看似合理的答案时，我们如何验证它？
> 人类专家的哪些能力是AI难以替代的？

---

## 概念讲解

### AI幻觉的本质

**幻觉 (Hallucination)** 是指AI生成看似合理但实际错误的内容。在空间AI中，这个问题尤为隐蔽和危险：

```
空间AI幻觉的类型

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  1. 几何幻觉                                                 │
│     - 生成无效的几何图形                                      │
│     - 错误的空间关系（如"A在B内部"实际为假）                    │
│     - 投影和坐标系混淆                                        │
│                                                             │
│  2. 语义幻觉                                                 │
│     - 对空间概念的错误理解                                    │
│     - 编造不存在的GIS功能                                     │
│     - 混淆专业术语                                           │
│                                                             │
│  3. 逻辑幻觉                                                 │
│     - 分析步骤的遗漏或重复                                    │
│     - 错误的因果推断                                         │
│     - 隐藏的假设未被说明                                      │
│                                                             │
│  4. 数据幻觉                                                 │
│     - 假设数据存在实际不存在                                  │
│     - 错误的数据格式假设                                      │
│     - 忽略数据质量和边界条件                                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘
```

### 为什么会产生幻觉？

| 原因类型 | 说明 | 空间AI中的例子 |
|---------|------|---------------|
| **训练数据偏差** | 模型见过的数据不具代表性 | 模型更多见过城市数据，对农村场景判断不准 |
| **模式匹配局限** | 模型基于模式而非理解 | 混淆buffer和convex hull因为结果看起来相似 |
| **上下文理解不足** | 无法完全理解复杂场景 | 忽略项目的特定约束条件 |
| **概率生成本质** | 逐token生成可能偏离 | 生成的代码引用不存在的函数 |
| **知识边界模糊** | 模型不知道自己不知道 | 对未见过的GIS版本编造功能 |

### 空间AI特有的脆弱性

空间分析有其特殊性质，使得AI的错误更具破坏性：

```
空间AI脆弱性来源

1. 隐式依赖
   GIS操作常有隐式前提：
   - "intersect前必须确保同一坐标系"
   - "buffer距离需要合适的投影"
   这些前提AI可能忽略

2. 级联效应
   空间分析通常是多步骤：
   数据加载 → 清理 → 投影 → 分析 → 输出
   早期错误会被放大

3. 验证困难
   空间结果不像代码能快速测试：
   - 这个生态源地识别对吗？
   - 这个阻力面合理吗？
   需要领域知识判断

4. 不可见错误
   某些空间错误不会立即显现：
   - 轻微的几何错误
   - 边界处的投影变形
   - 拓扑关系的细微错误
```

---

## 设计原理

### 验证框架设计

建立系统的验证流程是应对AI局限的关键：

```python
"""
空间AI结果验证框架
"""
from typing import Any, Dict, List, Optional
from dataclasses import dataclass
from enum import Enum

class ValidationLevel(Enum):
    """验证级别"""
    CRITICAL = "critical"  # 必须通过
    IMPORTANT = "important"  # 应该通过
    WARNING = "warning"  # 警告即可

@dataclass
class ValidationResult:
    """验证结果"""
    passed: bool
    level: ValidationLevel
    message: str
    details: Optional[Dict] = None

class SpatialAIValidator:
    """空间AI输出验证器"""

    def __init__(self):
        self.checks = []

    def add_check(self, check_fn, level: ValidationLevel):
        """添加验证检查"""
        self.checks.append((check_fn, level))
        return self

    def validate(self, result: Any, context: Dict) -> List[ValidationResult]:
        """执行所有验证"""
        results = []

        for check_fn, level in self.checks:
            try:
                result = check_fn(result, context)
                results.append(result)
            except Exception as e:
                results.append(ValidationResult(
                    passed=False,
                    level=ValidationLevel.CRITICAL,
                    message=f"验证失败: {str(e)}"
                ))

        return results

# === 常用验证检查 ===

def check_crs_consistency(result, context) -> ValidationResult:
    """检查坐标系一致性"""
    if hasattr(result, 'crs') and result.crs is not None:
        expected_crs = context.get('expected_crs')
        if expected_crs and result.crs != expected_crs:
            return ValidationResult(
                passed=False,
                level=ValidationLevel.CRITICAL,
                message=f"坐标系不匹配: 期望 {expected_crs}, 实际 {result.crs}",
                details={'expected': expected_crs, 'actual': result.crs}
            )
    return ValidationResult(
        passed=True,
        level=ValidationLevel.CRITICAL,
        message="坐标系检查通过"
    )

def check_geometry_validity(result, context) -> ValidationResult:
    """检查几何有效性"""
    if hasattr(result, 'geometry'):
        if hasattr(result.geometry, 'is_valid'):
            if not result.geometry.is_valid.all():
                invalid_count = (~result.geometry.is_valid).sum()
                return ValidationResult(
                    passed=False,
                    level=ValidationLevel.IMPORTANT,
                    message=f"存在 {invalid_count} 个无效几何",
                    details={'invalid_count': invalid_count}
                )
    return ValidationResult(
        passed=True,
        level=ValidationLevel.IMPORTANT,
        message="几何有效性检查通过"
    )

def check_result_size(result, context) -> ValidationResult:
    """检查结果规模是否合理"""
    if hasattr(result, '__len__'):
        size = len(result)
        max_expected = context.get('max_expected_size', float('inf'))
        min_expected = context.get('min_expected_size', 0)

        if size > max_expected:
            return ValidationResult(
                passed=False,
                level=ValidationLevel.WARNING,
                message=f"结果数量异常大: {size}",
                details={'size': size}
            )
        if size < min_expected:
            return ValidationResult(
                passed=False,
                level=ValidationLevel.WARNING,
                message=f"结果数量异常小: {size}",
                details={'size': size}
            )
    return ValidationResult(
        passed=True,
        level=ValidationLevel.WARNING,
        message="结果规模检查通过"
    )

def check_spatial_extent(result, context) -> ValidationResult:
    """检查空间范围是否合理"""
    if hasattr(result, 'total_bounds'):
        bounds = result.total_bounds
        expected_bounds = context.get('expected_bounds')

        if expected_bounds:
            # 检查结果是否在预期范围内
            if not (bounds[0] >= expected_bounds[0] and
                    bounds[2] <= expected_bounds[2] and
                    bounds[1] >= expected_bounds[1] and
                    bounds[3] <= expected_bounds[3]):
                return ValidationResult(
                    passed=False,
                    level=ValidationLevel.IMPORTANT,
                    message=f"空间范围超出预期",
                    details={'bounds': bounds, 'expected': expected_bounds}
                )
    return ValidationResult(
        passed=True,
        level=ValidationLevel.IMPORTANT,
        message="空间范围检查通过"
    )

# === 使用示例 ===

def create_validator_example():
    """创建完整的验证器示例"""
    validator = SpatialAIValidator()

    # 添加验证检查
    validator.add_check(check_crs_consistency, ValidationLevel.CRITICAL)
    validator.add_check(check_geometry_validity, ValidationLevel.IMPORTANT)
    validator.add_check(check_result_size, ValidationLevel.WARNING)
    validator.add_check(check_spatial_extent, ValidationLevel.IMPORTANT)

    return validator

if __name__ == "__main__":
    print("=== 空间AI验证框架 ===\n")

    validator = create_validator_example()
    print(f"验证器配置了 {len(validator.checks)} 个检查")

    print("\n验证级别说明:")
    print("  CRITICAL: 必须通过的错误")
    print("  IMPORTANT: 应该通过的问题")
    print("  WARNING: 值得注意的警告")
```

### 人类专家的不可替代性

```
人类专家的优势领域

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  1. 上下文理解                                             │
│     - 理解项目背景和约束条件                                 │
│     - 识别"不合理"的结果                                     │
│     - 考虑实际可行性                                         │
│                                                             │
│  2. 价值判断                                               │
│     - 权衡不同目标                                           │
│     - 考虑伦理影响                                           │
│     - 平衡科学性和实用性                                     │
│                                                             │
│  3. 创造性思维                                             │
│     - 提出新的分析方法                                       │
│     - 创造性地解决问题                                       │
│     - 跨领域联想                                             │
│                                                             │
│  4. 责任承担                                               │
│     - 对结果负责                                             │
│     - 解释和辩护决策                                         │
│     - 承担法律和伦理责任                                     │
│                                                             │
└─────────────────────────────────────────────────────────────┘
```

### AI辅助的正确模式

```
正确的AI使用模式

专家 + AI = 增强

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  AI的角色                            专家的角色             │
│    │                                   │                   │
│    ├── 快速计算和数据处理 ──────────────┼── 定义问题         │
│    ├── 提供多种方案 ───────────────────┼── 选择和评估       │
│    ├── 识别模式 ──────────────────────┼── 解释意义         │
│    ├── 自动化重复任务 ─────────────────┼── 设计工作流       │
│    ├── 检查错误 ──────────────────────┼── 验证关键结果      │
│    └── 提供参考 ──────────────────────┼── 做出决策         │
│                                                             │
└─────────────────────────────────────────────────────────────┘

错误模式:
  AI ──→ 结果 ──→ 直接使用
  (跳过专家验证)

正确模式:
  专家 ──→ 定义问题 ──→ AI ──→ 候选方案
                             │
  专家 ◄─────────────────────┘
     │ 评估
     │ 验证
     │ 决策
     ↓
  最终方案
```

---

## 案例分析

### 案例1：坐标系统错误

**场景**：AI生成了生态源地识别代码，但忘记处理坐标系问题。

```python
# AI生成的代码（有潜在问题）
def identify_sources(ai_generated_landcover):
    """AI生成的源地识别代码"""
    # 直接使用原始数据分析
    forest = ai_generated_landcover[ai_generated_landcover['type'] == 'forest']
    sources = forest[forest['area'] > 100]  # 面积阈值

    # 问题：数据可能是WGS84，但面积按度计算
    return sources

# 验证和修正
def identify_sources_validated(landcover, target_crs='EPSG:3857'):
    """添加验证的版本"""
    # 验证1：检查坐标系
    if landcover.crs and landcover.crs.is_geographic:
        # 需要投影
        landcover_projected = landcover.to_crs(target_crs)
        print(f"注意：数据已从 {landcover.crs} 投影到 {target_crs}")
    else:
        landcover_projected = landcover

    # 验证2：面积计算检查
    if landcover_projected.crs.is_geographic:
        raise ValueError("不能在地理坐标系中计算面积")

    # 进行分析
    forest = landcover_projected[landcover_projected['type'] == 'forest']
    sources = forest[forest.geometry.area > 100000]  # 投影后单位是米

    # 验证3：结果合理性检查
    if len(sources) == 0:
        print("警告：没有识别到源地，检查面积阈值")
    if len(sources) > len(landcover_projected) * 0.9:
        print("警告：几乎全部区域都是源地，检查阈值")

    return sources
```

### 案例2：拓扑关系幻觉

**场景**：AI错误判断空间关系。

```python
# AI可能生成的错误逻辑
def check_connectivity(patch_a, patch_b):
    """检查两个斑块的连通性"""
    # 问题：AI可能混淆多种连通性判断
    return patch_a.intersects(patch_b)  # 相交不等于连通

# 正确的方法
def check_connectivity_robust(patch_a, patch_b, distance_threshold=100):
    """
    鲁棒的连通性检查

    需要明确：
    1. 是直接连接还是距离阈值内？
    2. 需要考虑阻力吗？
    3. 连通的宽度要求？
    """
    # 方案1：直接接触
    if patch_a.touches(patch_b):
        return {'connected': True, 'type': 'direct'}

    # 方案2：距离阈值
    distance = patch_a.distance(patch_b)
    if distance <= distance_threshold:
        return {'connected': True, 'type': 'proximity', 'distance': distance}

    return {'connected': False, 'distance': distance}
```

### 案例3：参数选择幻觉

**场景**：AI编造了一个"标准"参数值，实际并不存在。

```python
# AI可能这样写
def calculate_landscape_metrics(patch, resistance="standard"):
    """
    计算景观指标

    问题：AI声称存在"standard"阻力值，实际需要根据情况设定
    """
    # 不存在通用标准
    pass

# 正确的做法
def calculate_landscape_metrics_validated(patch, resistance=None,
                                          resistance_params=None):
    """
    计算景观指标，明确参数来源

    Args:
        resistance: 阻力值，必须明确提供
        resistance_params: 阻力参数配置

    Returns:
        指标和参数来源说明
    """
    if resistance is None and resistance_params is None:
        raise ValueError(
            "阻力参数必须明确提供。不存在'标准'值。"
            "请根据研究区域和物种特征设定。"
        )

    # 记录参数来源
    metadata = {
        'resistance_source': resistance_params.get('source', 'user_provided'),
        'reference': resistance_params.get('reference', None),
        'justification': resistance_params.get('justification', None)
    }

    # 计算指标...
    return {'metrics': {}, 'metadata': metadata}
```

---

## 反思与延伸

### 思考问题

1. **识别能力边界**：你最近一次发现AI错误是什么时候？是如何发现的？

2. **验证成本**：在什么情况下，详细验证的成本超过了使用AI的收益？

3. **责任分配**：当AI辅助的分析出现错误时，责任该如何划分？

4. **信任建立**：随着时间推移，你应该如何调整对AI的信任程度？

### 实践练习

1. **错误审计**：回顾过去使用AI生成的空间分析代码，找出潜在问题

2. **验证清单**：为你常用的空间分析类型建立验证清单

3. **对比实验**：同一个问题让AI多次求解，比较结果的差异

### 延伸阅读

- **"Human Compatible"** (Stuart Russell) - AI对齐与人类价值
- **"AI Safety"** 相关文献 - 理解AI的局限和风险
- GIS最佳实践手册 - 学习领域专家的验证方法

---

## 关键要点

1. **AI在空间分析中可能产生多种类型的幻觉**，需要系统性验证
2. **建立验证框架**是可靠使用AI的关键
3. **人类专家的角色不可替代**，特别是在判断和决策环节
4. **正确的使用模式是AI辅助+专家验证**，而非AI替代
5. **保持批判性思维**，理解AI的局限才能更好地利用它
