# 实践案例00：搭建你的第一个空间AI助手

## 目标

通过本实践，你将：
1. 配置Claude Code环境
2. 创建一个简单的空间查询技能
3. 理解Agent如何调用工具
4. 建立对后续学习的信心

---

## 步骤1：环境准备

### 安装Claude Code

```bash
# 使用npm安装
npm install -g @anthropic-ai/claude-code

# 验证安装
claude --version
```

### 配置API密钥

```bash
# 设置API密钥
claude config set api_key your_anthropic_api_key

# 或使用环境变量
export ANTHROPIC_API_KEY=your_key
```

### 安装Python依赖

```bash
# 创建虚拟环境
python -m venv venv
source venv/bin/activate  # Linux/Mac
# 或
venv\Scripts\activate  # Windows

# 安装依赖
pip install geopandas shapely matplotlib pandas
```

---

## 步骤2：创建空间查询技能

### 2.1 创建技能目录

```bash
mkdir -p .claude/skills
```

### 2.2 编写技能文件

创建 `.claude/skills/spatial-query.md`：

```markdown
---
name: spatial-query
description: 执行基础空间查询和分析
parameters:
  - data_file: 空间数据文件路径
  - query_type: 查询类型（buffer/intersect/nearest）
  - distance: 缓冲距离（用于buffer查询）
---

## 空间查询技能

当用户需要进行空间查询时，使用此技能。

### 支持的查询类型

1. **buffer**: 缓冲区分析
2. **intersect**: 相交分析
3. **nearest**: 最近邻查找

### 执行流程

1. 读取空间数据
2. 根据查询类型执行相应操作
3. 返回结果和统计信息
4. 可选：生成可视化
```

---

## 步骤3：实现技能逻辑

创建 `examples/spatial_helper.py`：

```python
"""
简单的空间分析助手
演示AI如何理解并执行空间任务
"""

import geopandas as gpd
from shapely.geometry import Point
import matplotlib.pyplot as plt

class SpatialHelper:
    """空间分析助手类"""

    def __init__(self, data_path=None):
        self.data = None
        if data_path:
            self.load_data(data_path)

    def load_data(self, path):
        """加载空间数据"""
        try:
            self.data = gpd.read_file(path)
            return f"成功加载 {len(self.data)} 个空间要素"
        except Exception as e:
            return f"加载失败: {str(e)}"

    def buffer_analysis(self, distance, crs=None):
        """缓冲区分析"""
        if self.data is None:
            return "请先加载数据"

        if crs:
            # 转换到适合距离计算的坐标系
            self.data = self.data.to_crs(crs)

        buffered = self.data.buffer(distance)
        result = gpd.GeoDataFrame(geometry=buffered, crs=self.data.crs)

        return {
            'count': len(result),
            'total_area': result.geometry.area.sum(),
            'geometry': result
        }

    def intersect_analysis(self, other_data):
        """相交分析"""
        if self.data is None:
            return "请先加载数据"

        intersection = self.data.intersection(other_data)
        valid_results = intersection[~intersection.is_empty]

        return {
            'intersecting_count': len(valid_results),
            'geometries': valid_results
        }

    def nearest_neighbor(self, point, n=1):
        """最近邻查找"""
        if self.data is None:
            return "请先加载数据"

        if isinstance(point, (tuple, list)):
            point = Point(point)

        distances = self.data.geometry.distance(point)
        nearest_indices = distances.nsmallest(n).index

        results = []
        for idx in nearest_indices:
            results.append({
                'index': idx,
                'distance': distances[idx],
                'geometry': self.data.loc[idx].geometry
            })

        return results

    def summarize(self):
        """数据摘要"""
        if self.data is None:
            return "请先加载数据"

        return {
            'count': len(self.data),
            'crs': str(self.data.crs),
            'bounds': self.data.total_bounds,
            'geometry_types': self.data.geometry.type.value_counts().to_dict()
        }

    def visualize(self, output_path=None):
        """可视化"""
        if self.data is None:
            return "请先加载数据"

        fig, ax = plt.subplots(figsize=(10, 10))
        self.data.plot(ax=ax, alpha=0.5, edgecolor='k')
        ax.set_title('Spatial Data Visualization')
        ax.set_axis_off()

        if output_path:
            plt.savefig(output_path, bbox_inches='tight', dpi=300)
            return f"图表已保存到 {output_path}"

        plt.show()
        return "图表已显示"

# 创建一个示例数据集用于测试
def create_sample_data():
    """创建示例空间数据"""
    import numpy as np

    np.random.seed(42)

    # 创建一些随机点
    points = [Point(np.random.uniform(-100, 100),
                    np.random.uniform(-100, 100))
              for _ in range(20)]

    # 转换为GeoDataFrame
    gdf = gpd.GeoDataFrame({
        'id': range(20),
        'value': np.random.randint(1, 100, 20),
        'category': np.random.choice(['A', 'B', 'C'], 20)
    }, geometry=points, crs='EPSG:4326')

    # 保存为GeoJSON
    gdf.to_file('sample_data.geojson', driver='GeoJSON')
    return gdf

if __name__ == "__main__":
    # 创建示例数据
    print("创建示例数据...")
    create_sample_data()

    # 测试SpatialHelper
    print("\n初始化空间助手...")
    helper = SpatialHelper('sample_data.geojson')

    print("\n数据摘要:")
    print(helper.summarize())

    print("\n缓冲区分析:")
    buffer_result = helper.buffer_analysis(10)
    print(f"缓冲区数量: {buffer_result['count']}")
    print(f"总缓冲面积: {buffer_result['total_area']:.2f}")

    print("\n最近邻查找:")
    nearest = helper.nearest_neighbor((0, 0), n=3)
    for i, n in enumerate(nearest, 1):
        print(f"  {i}. 距离: {n['distance']:.2f}")

    print("\n生成可视化...")
    print(helper.visualize('spatial_visualization.png'))
```

---

## 步骤4：在Claude Code中使用

### 4.1 启动Claude Code

```bash
cd /path/to/CC4SI
claude
```

### 4.2 与Claude对话

```
你: 我有一个空间数据文件sample_data.geojson，帮我分析一下

Claude: 让我先读取这个文件看看...

[读取 sample_data.geojson]

这是一个包含20个点要素的GeoJSON文件，坐标系统为WGS84 (EPSG:4326)。
每个点都有id、value和category属性。

你想要进行什么分析？

你: 找出距离原点最近的3个点

Claude: 我来帮你找出距离原点最近的点。

[调用 spatial-query 技能]

结果：
1. 最近点 (id=7): 距离约 15.2 单位
2. 第二近点 (id=12): 距离约 23.8 单位
3. 第三近点 (id=3): 距离约 31.5 单位

需要我生成可视化吗？
```

---

## 步骤5：理解工作原理

### AI系统的思考过程

```
用户请求 ──→ [意图识别] ──→ [任务分解]
                  │               │
                  ↓               ↓
            这是空间查询       需要执行：
            任务                  1. 加载数据
                                  2. 计算距离
                                  3. 排序取前N
                  │               │
                  ↓               ↓
            [选择技能] ──→ [调用工具]
                  │               │
                  ↓               ↓
            spatial-query    spatial_helper.py
                  │               │
                  └───────┬───────┘
                          ↓
                    [整合结果]
                          ↓
                    [返回用户]
```

### 关键概念验证

| 概念 | 实践体现 |
|-----|---------|
| Agent | Claude Code作为智能体，理解意图并协调执行 |
| Skill | spatial-query技能封装了空间分析能力 |
| Tool | spatial_helper.py是具体实现工具 |

---

## 反思问题

1. **理解验证**：你能在脑海中复述一遍AI执行这个任务的流程吗？

2. **扩展思考**：如果要让这个助手支持更多空间操作，应该如何设计？

3. **局限性**：当前实现有哪些不足？如何改进？

4. **迁移应用**：这个模式可以应用到你的专业领域吗？

---

## 下一步

完成这个实践后，你已经：
- ✅ 配置了Claude Code环境
- ✅ 创建了第一个空间分析技能
- ✅ 理解了Agent的基本工作方式

准备好进入下一章：**01-foundations（基础原理）**
