LangSC 1.0.6
Language Structure Computation - GPF, BCC, and JSS unified package
License: MIT
Requires Python: >=3.6

# LangSC 使用手册

**LangSC**（Language Structure Computation）是一个统一的 Python 包，集成了自然语言结构分析、语料库查询和 JSON 结构检索三大功能。

---

## 目录

- [1. 概述](#1-概述)
- [2. 安装与配置](#2-安装与配置)
- [3. 快速上手](#3-快速上手)
- [4. GPF 类 — 自然语言结构分析](#4-gpf-类--自然语言结构分析)
  - [4.1 构造函数与初始化](#41-构造函数与初始化)
  - [4.2 自动索引机制](#42-自动索引机制)
  - [4.3 NLP 分析](#43-nlp-分析)
  - [4.4 文本与网格操作](#44-文本与网格操作)
  - [4.5 Unit（语言单元）操作](#45-unit语言单元操作)
  - [4.6 Relation（关系）操作](#46-relation关系操作)
  - [4.7 Grid KV（网格属性）](#47-grid-kv网格属性)
  - [4.8 Table（数据表）操作](#48-table数据表操作)
  - [4.9 FSA（有限状态自动机）](#49-fsa有限状态自动机)
  - [4.10 索引创建](#410-索引创建)
  - [4.11 服务调用与 Dot 可视化](#411-服务调用与-dot-可视化)
  - [4.12 结构添加](#412-结构添加)
  - [4.13 可视化输出](#413-可视化输出)
  - [4.14 其他方法](#414-其他方法)
  - [4.15 GPF 方法速查表](#415-gpf-方法速查表)
- [5. BCC 类 — 语料库查询](#5-bcc-类--语料库查询)
  - [5.1 构造函数与初始化](#51-构造函数与初始化)
  - [5.2 自动索引机制](#52-自动索引机制)
  - [5.3 语料查询](#53-语料查询)
  - [5.4 KV 操作](#54-kv-操作)
  - [5.5 语料索引](#55-语料索引)
  - [5.6 BCC 方法速查表](#56-bcc-方法速查表)
- [6. JSS 类 — JSON 结构检索](#6-jss-类--json-结构检索)
  - [6.1 构造函数与初始化](#61-构造函数与初始化)
  - [6.2 自动索引机制](#62-自动索引机制)
  - [6.3 数据目录结构](#63-数据目录结构)
  - [6.4 cfg 配置文件格式](#64-cfg-配置文件格式)
  - [6.5 cfg 自动生成规则](#65-cfg-自动生成规则)
  - [6.6 查询](#66-查询)
  - [6.7 资源释放](#67-资源释放)
  - [6.8 JSS 方法速查表](#68-jss-方法速查表)
- [7. 完整示例](#7-完整示例)
- [8. 数据文件格式说明](#8-数据文件格式说明)
- [9. 平台与依赖](#9-平台与依赖)
- [10. 参考文献](#10-参考文献)

---

## 1. 概述

LangSC 包含三个相互独立的核心类：

| 类 | 功能 | 底层库 | 索引日志 |
|---|------|--------|----------|
| **GPF** | 基于网格（Lattice/Grid）的自然语言结构分析框架，支持分词、词性标注、句法分析、FSA 规则匹配、数据表查询和可视化 | `gpflib` | `IdxLog_GPF.txt` |
| **BCC** | BCC 语料库查询引擎，支持词频统计、上下文检索、计数查询和语料索引 | `bcclib` | `IdxLog_BCC.txt` |
| **JSS** | JSON 结构化数据检索引擎，支持 SQL 风格查询、多表管理和自动建索引 | `jsslib` | `IdxLog_JSS.txt` |

三个类**相互独立**，按需导入即可，不会加载多余的动态库。例如只使用 JSS 时，不会加载 `gpflib` 和 `bcclib`。

### 架构设计

```
LangSC/
├── __init__.py        # 导出 GPF, BCC, JSS, __version__
├── __version__.py     # 版本号
├── _utils.py          # 共享工具函数（编码检测、索引日志管理等）
├── gpf.py             # GPF 类（封装 gpflib）
├── bcc.py             # BCC 类（封装 bcclib）
├── jss.py             # JSS 类（封装 jsslib）
├── gpflib.dll / libgpflib.so / libgpflib.dylib
├── bcclib.dll / libbcclib.so / libbcclib.dylib
├── jsslib.dll / libjsslib.so / libjsslib.dylib
└── (数据文件: GPFconfig.txt, BCCconfig.txt, Parser.lua, Segment.dat, idxPOS.dat, base.lex)
```

---

## 2. 安装与配置

### 2.1 安装

```bash
pip install LangSC
```

### 2.2 依赖

| 依赖包 | 用途 | 说明 |
|--------|------|------|
| `pywin32` | Windows DLL 内存释放 | 仅 Windows 平台需要 |
| `wordcloud` | 词云可视化 | GPF 的 ShowCloud 方法使用 |
| `requests` | HTTP 请求 | GPF 的 DotFile/DotBuff 远程服务使用 |
| `chardet` | 文件编码自动检测 | 全部三个类使用 |

### 2.3 系统要求

- **Python** >= 3.6
- **操作系统**：Windows、Linux、macOS
- **Graphviz**（可选）：GPF 可视化输出需要安装 Graphviz 的 `dot` 命令，或使用包内自带的 `Graph/dot` 工具

### 2.4 版本查询

```python
import LangSC
print(LangSC.__version__)  # 例如 "1.0.1"
```

---

## 3. 快速上手

```python
# GPF：分词
from LangSC import GPF
gpf = GPF("./data")
result = gpf.Segment("自然语言处理是人工智能的重要方向")
print(result)  # "自然 语言 处理 是 人工 智能 的 重要 方向"

# BCC：词频查询
from LangSC import BCC
bcc = BCC("./corpus")
freq = bcc.RunBCC("学习", Command="Freq", Number=10)
print(freq)

# JSS：SQL 查询
from LangSC import JSS
jss = JSS("./table")
results = jss.RunJSS("SELECT TOP 5 id, ci FROM ci WHERE ci = '爱';")
for row in results:
    print(row)
jss.Terminate()
```

---

## 4. GPF 类 — 自然语言结构分析

GPF（Grid-based Parsing Framework）提供基于网格的自然语言结构分析能力。核心数据结构是**网格（Grid/Lattice）**，其中包含**语言单元（Unit）**和**关系（Relation）**，支持文本分析、规则匹配、词表查询和结构可视化。

### 4.1 构造函数与初始化

```python
from LangSC import GPF

gpf = GPF(dataPath="./data")
```

**参数**

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `dataPath` | `str` | `"./data"` | 数据目录路径，包含 Table 和 FSA 文件 |

**说明**
- 构造函数自动初始化 GPF 网格句柄（`hHandleGPF`）和 CRF/POS 句柄（`hHandleCRFPOS`）
- 自动加载 CRF 分词模型（`Segment.dat`）和词性标注数据（`idxPOS.dat`）
- 自动检测数据目录状态并执行索引（详见 [4.2 自动索引机制](#42-自动索引机制)）
- `dataPath` 中的反斜杠会被自动转换为正斜杠

### 4.2 自动索引机制

构造函数调用 `_init_gpf_data(dataPath)` 自动处理数据索引：

1. 检查 `dataPath` 中是否存在 `IdxLog_GPF.txt` 索引日志
2. **若存在**：说明已是索引目录，直接使用
3. **若不存在**：视为原始数据目录
   - 扫描目录下的 Table 和 FSA 文件
   - 创建 `dataPathIdx/` 索引目录
   - 逐一索引 Table 和 FSA 文件，并记录到 `IdxLog_GPF.txt`
4. 通过文件时间戳比较（`is_same`），避免重复索引

> 索引完成后，`self.dataPath` 指向实际的索引目录路径。

### 4.3 NLP 分析

#### `Segment(text, table="")`

对文本执行 CRF 分词。

```python
result = gpf.Segment("自然语言处理是人工智能的重要方向")
# 返回: "自然 语言 处理 是 人工 智能 的 重要 方向"
```

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `text` | `str` | （必填） | 待分词的文本 |
| `table` | `str` | `""` | 用户词表名称。为空时使用 CRF 模型分词；指定时使用用户词表辅助分词 |

**返回值**：`str`，以空格分隔的分词结果。

**说明**
- 首次调用时自动初始化 CRF 模型（线程安全）
- 若指定 `table`，会先调用 `SetGridText` 设置文本，再使用 `GPF_GridSegUser` 进行带用户词表的分词

#### `POS(text, table="")`

对文本执行词性标注（先分词，再标注）。

```python
result = gpf.POS("自然语言处理是人工智能的重要方向")
# 返回: "自然/b 语言/n 处理/v 是/v 人工/b 智能/n 的/u 重要/a 方向/n"
```

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `text` | `str` | （必填） | 待标注的文本 |
| `table` | `str` | `""` | 用户词表名称 |

**返回值**：`str`，格式为 `词/词性` 以空格分隔。

**说明**
- 首次调用时自动初始化 POS 模型（线程安全）
- 内部先调用 `Segment` 分词，再调用 `GPF_POS` 标注

#### `Parse(text, **Others)`

统一解析接口，根据 `Structure` 参数调用不同的解析方式。

```python
# 分词
result = gpf.Parse("自然语言处理", Structure="Segment")

# 词性标注
result = gpf.Parse("自然语言处理", Structure="POS")

# 句法树（需要远程服务）
result = gpf.Parse("自然语言处理", Structure="Tree")

# 指定用户词表
result = gpf.Parse("自然语言处理", Structure="Segment", Table="myDict")

# 通过 Web 服务解析
result = gpf.Parse("自然语言处理", Structure="POS", Web=True)
```

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `text` | `str` | （必填） | 待解析文本（自动截断至 1024 字符） |
| `Structure` | `str` | `"POS"` | 解析类型：`"Segment"` / `"POS"` / `"Tree"` / `"Chunk"` 等 |
| `Web` / `IsWeb` | `bool` | `False` | 是否通过 Web 服务解析 |
| `Table` | `str` | `""` | 用户词表名称 |

**返回值**：`str`，JSON 格式字符串。
- `Segment`：`["词1", "词2", ...]`
- `POS`：`["词1/POS1", "词2/POS2", ...]`
- 其他：由远程服务返回的 JSON 结构

### 4.4 文本与网格操作

GPF 的核心数据结构是**网格（Grid）**，网格承载文本、语言单元（Unit）和关系（Relation）。

#### `SetText(text)` / `SetGridText(text)`

设置网格的文本内容。

```python
gpf.SetText("今天天气很好")
# 或
gpf.SetGridText("今天天气很好")  # 等价，但额外调用 GPFInit
```

| 参数 | 类型 | 说明 |
|------|------|------|
| `text` | `str` | 文本内容 |

**返回值**：`int`，操作状态码。

#### `GetText(begin=0, end=-1)` / `GetGridText(begin=0, end=-1)`

获取网格中的文本。

```python
text = gpf.GetText()           # 获取全部文本
text = gpf.GetText(0, 3)       # 获取位置 0 到 3 的文本
text = gpf.GetGridText()       # 等价于 GetText()
```

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `begin` | `int` | `0` | 起始位置 |
| `end` | `int` | `-1` | 结束位置（`-1` 表示全部） |

**返回值**：`str`，文本内容。

#### `GetGrid()` / `GetStructure()`

获取完整的网格结构（JSON 格式）。

```python
grid = gpf.GetGrid()        # 返回网格的 JSON 表示
grid = gpf.GetStructure()   # 等价
```

**返回值**：`dict` / `list`，网格结构的 JSON 对象。若网格为空返回 `{}`。

### 4.5 Unit（语言单元）操作

Unit 是网格中的基本语言单元，对应一个词或短语，具有位置信息和键值属性。

#### `AddUnit(text, colNo=-1)`

向网格中添加一个 Unit。

```python
unitNo = gpf.AddUnit("天气")           # 自动定位
unitNo = gpf.AddUnit("天气", colNo=3)  # 指定列号（文本中的字符位置）
```

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `text` | `str` | （必填） | Unit 的文本内容 |
| `colNo` | `int` | `-1` | 列号（字符位置）。`-1` 时自动查找文本位置 |

**返回值**：`str`，Unit 编号（如 `"(0,2)"`），后续操作通过此编号引用该 Unit。

#### `AddUnitKV(unitNo, key, val)`

为 Unit 添加键值属性。

```python
gpf.AddUnitKV(unitNo, "POS", "n")         # 添加词性
gpf.AddUnitKV(unitNo, "Tag", "人名;地名")  # 多值用分隔符
```

| 参数 | 类型 | 说明 |
|------|------|------|
| `unitNo` | `str` | Unit 编号 |
| `key` | `str` | 属性名 |
| `val` | `str` | 属性值。支持以空格、分号、逗号、制表符分隔的多值，每个值分别添加 |

**返回值**：`int`，固定返回 `1`。

#### `GetWord(unitNo)`

获取 Unit 的文本内容。

```python
word = gpf.GetWord(unitNo)  # 例如 "天气"
```

| 参数 | 类型 | 说明 |
|------|------|------|
| `unitNo` | `str` | Unit 编号 |

**返回值**：`str`，Unit 的文本内容。

#### `GetUnit(kv, UnitNo="", UExpress="")` / `GetUnits(kv, UnitNo="", UExpress="")`

按条件查找 Unit。

```python
units = gpf.GetUnit("POS=n")           # 查找所有词性为 n 的 Unit
units = gpf.GetUnits("POS=n")          # 同上
unit  = gpf.GetUnit(0)                 # 按 FSA 路径号获取（整数参数）
```

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `kv` | `str` 或 `int` | （必填） | 查询条件（如 `"POS=n"`）或 FSA 路径号（整数） |
| `UnitNo` | `str` | `""` | 限定在某个 Unit 范围内查找 |
| `UExpress` | `str` | `""` | Unit 表达式 |

**返回值**：
- 查找模式：`list` / `dict`，匹配的 Unit 列表。无匹配返回 `0`
- FSA 路径号模式：`str`，Unit 编号

#### `GetUnitKV(unitNo, key="")` / `GetUnitKVs(unitNo, key="")`

获取 Unit 的属性值。

```python
kvs = gpf.GetUnitKV(unitNo)              # 获取全部属性 → dict
val = gpf.GetUnitKV(unitNo, "POS")       # 获取指定属性 → list
word = gpf.GetUnitKV(unitNo, "Word")     # 获取文本 → str
pos = gpf.GetUnitKV(unitNo, "From")      # 获取起始位置 → int
```

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `unitNo` | `str` | （必填） | Unit 编号 |
| `key` | `str` | `""` | 属性名。为空返回全部属性 |

**返回值**：
| `key` 值 | 返回类型 | 说明 |
|-----------|----------|------|
| `""` | `dict` | 全部属性键值对 |
| `"Word"` / `"HeadWord"` | `str` | 文本内容（无匹配返回 `""` |
| `"From"` / `"To"` | `int` | 位置信息（无匹配返回 `-1`） |
| 其他 | `list` | 属性值列表 |

#### `GetFSAUnit(pathNo)`

按 FSA 路径号获取 Unit。

```python
unit = gpf.GetFSAUnit(0)  # 获取第 0 条路径对应的 Unit
```

| 参数 | 类型 | 说明 |
|------|------|------|
| `pathNo` | `int` | FSA 路径号 |

**返回值**：`str`，Unit 编号。

#### `IsUnit(unitNo, kv)`

判断 Unit 是否具有指定属性。

```python
ret = gpf.IsUnit(unitNo, "POS=n")      # 判断词性是否为 n
ret = gpf.IsUnit(unitNo, "Type=Word")   # 判断类型是否为 Word
```

| 参数 | 类型 | 说明 |
|------|------|------|
| `unitNo` | `str` | Unit 编号 |
| `kv` | `str` | 属性条件，格式为 `"Key=Value"` |

**返回值**：`int`，匹配返回非零值，不匹配返回 `0`。

### 4.6 Relation（关系）操作

Relation 表示两个 Unit 之间的有向关系（如主谓、动宾等）。

#### `AddRelation(unitNo1, unitNo2, role)`

添加关系。

```python
gpf.AddRelation(unitNo1, unitNo2, "SBJ")  # unitNo1 → unitNo2, 关系为 SBJ（主语）
```

| 参数 | 类型 | 说明 |
|------|------|------|
| `unitNo1` | `str` | 源 Unit 编号（关系起点） |
| `unitNo2` | `str` | 目标 Unit 编号（关系终点） |
| `role` | `str` | 关系类型（如 `"SBJ"`, `"OBJ"`, `"ATT"` 等） |

**返回值**：`int`，固定返回 `1`。

#### `AddRelationKV(unitNo1, unitNo2, role, key, val)`

为关系添加键值属性。

```python
gpf.AddRelationKV(unitNo1, unitNo2, "SBJ", "Confidence", "0.95")
```

| 参数 | 类型 | 说明 |
|------|------|------|
| `unitNo1` | `str` | 源 Unit 编号 |
| `unitNo2` | `str` | 目标 Unit 编号 |
| `role` | `str` | 关系类型 |
| `key` | `str` | 属性名 |
| `val` | `str` | 属性值（支持多值分隔） |

**返回值**：`int`，固定返回 `1`。

#### `GetRelation(kv="")` / `GetRelations(kv="")`

获取关系列表。

```python
rels = gpf.GetRelation()               # 获取全部关系
rels = gpf.GetRelations("Role=SBJ")    # 按条件过滤
```

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `kv` | `str` | `""` | 过滤条件（为空返回全部） |

**返回值**：`list`，关系列表。无关系返回 `[]`。

#### `GetRelationKV(unitNo1, unitNo2, role, key="")` / `GetRelationKVs(...)`

获取关系属性。

```python
kvs = gpf.GetRelationKV(unitNo1, unitNo2, "SBJ")          # 全部属性
kvs = gpf.GetRelationKVs(unitNo1, unitNo2, "SBJ", "key")  # 指定属性
```

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `unitNo1` | `str` | （必填） | 源 Unit 编号 |
| `unitNo2` | `str` | （必填） | 目标 Unit 编号 |
| `role` | `str` | （必填） | 关系类型 |
| `key` | `str` | `""` | 属性名（为空返回全部） |

**返回值**：`dict` / `list`，属性键值对。

#### `IsRelation(unitNo1, unitNo2, role, kv="")`

判断两个 Unit 之间是否存在指定关系。

```python
ret = gpf.IsRelation(unitNo1, unitNo2, "SBJ")
```

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `unitNo1` | `str` | （必填） | 源 Unit 编号 |
| `unitNo2` | `str` | （必填） | 目标 Unit 编号 |
| `role` | `str` | （必填） | 关系类型 |
| `kv` | `str` | `""` | 附加属性条件 |

**返回值**：`int`，存在返回非零值，不存在返回 `0`。

### 4.7 Grid KV（网格属性）

为整个网格（非某个 Unit）添加/获取全局属性。

#### `AddGridKV(key, val)` / `AddTextKV(key, val)`

添加网格级属性。

```python
gpf.AddGridKV("Author", "张三")
gpf.AddTextKV("Source", "新闻")   # 等价
```

| 参数 | 类型 | 说明 |
|------|------|------|
| `key` | `str` | 属性名 |
| `val` | `str` | 属性值（支持多值分隔） |

**返回值**：`int`，固定返回 `0`。

#### `GetGridKV(key="")` / `GetGridKVs(key="")` / `GetTextKV(key="")`

获取网格级属性。

```python
kvs = gpf.GetGridKV()           # 全部属性
kvs = gpf.GetGridKV("Author")   # 指定属性
kvs = gpf.GetTextKV("Source")   # 等价于 GetGridKVs
```

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `key` | `str` | `""` | 属性名（为空返回全部） |

**返回值**：`dict` / `list`，属性键值对。

### 4.8 Table（数据表）操作

Table 是 GPF 的词表/数据表系统，支持键值查询、前后缀匹配等操作。

#### `SetTable(tableName)`

设置当前活跃的数据表。

```python
gpf.SetTable("CiDian")
```

#### `CallTable(tableName, Mode=0)`

加载并设置数据表。

```python
gpf.CallTable("CiDian")
```

**说明**：先调用 `GPF_AppLexicon` 加载表，再调用 `GPF_SetLexicon` 设置为当前表。

#### `GetTable()`

获取所有已加载的表名。

```python
tables = gpf.GetTable()  # → dict/list
```

**返回值**：`dict`，所有表名及其信息。

#### `GetTableItem(tableName="", kv="")` / `GetItem(tableName="", kv="")`

获取表中的条目列表。

```python
items = gpf.GetTableItem("CiDian")           # 获取表的全部条目
items = gpf.GetTableItem("CiDian", "POS=n")  # 按条件过滤
items = gpf.GetItem("CiDian")                # 等价
```

#### `GetTableItems(tableName, kv="")`

获取指定表的条目列表（带过滤条件）。

```python
items = gpf.GetTableItems("CiDian", "POS=n")
```

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `tableName` | `str` | （必填） | 表名 |
| `kv` | `str` | `""` | 过滤条件 |

**返回值**：`dict` / `list`，条目列表。

#### `GetTableItemKV(tableName, item="", key="")` / `GetItemKV(...)` / `GetTableItemKVs(...)`

获取表中某条目的属性。

```python
kvs = gpf.GetTableItemKV("CiDian", "天气")               # 全部属性
kvs = gpf.GetTableItemKVs("CiDian", "天气", "POS")        # 指定属性
kvs = gpf.GetItemKV("CiDian", "天气", "POS")              # 等价
```

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `tableName` | `str` | （必填） | 表名 |
| `item` | `str` | `""` | 条目名 |
| `key` | `str` | `""` | 属性名（为空返回全部） |

**返回值**：`dict` / `list`。

#### `IsTable(tableName, item="", kv="")`

判断表中是否存在指定条目或属性。

```python
ret = gpf.IsTable("CiDian")                        # 判断表是否存在
ret = gpf.IsTable("CiDian", "天气")                # 判断条目是否存在
ret = gpf.IsTable("CiDian", "天气", "POS=n")       # 判断属性是否匹配
```

**返回值**：`int`，存在/匹配返回非零值。

#### `GetSuffix(tableName, sentence)` / `GetPrefix(tableName, sentence)`

后缀/前缀匹配。

```python
suffix = gpf.GetSuffix("CiDian", "今天天气很好")  # 从文本尾部匹配
prefix = gpf.GetPrefix("CiDian", "今天天气很好")  # 从文本头部匹配
```

| 参数 | 类型 | 说明 |
|------|------|------|
| `tableName` | `str` | 表名 |
| `sentence` | `str` | 待匹配的文本 |

**返回值**：`str`，匹配结果。

### 4.9 FSA（有限状态自动机）

FSA 是 GPF 的规则引擎，支持基于状态自动机的模式匹配和规则执行。

#### `CallFSA(fsaName, **Others)` / `RunFSA(fsaName, param="")`

执行 FSA 规则。

```python
gpf.CallFSA("myRule", Param1="val1", Param2="val2")
gpf.RunFSA("myRule")   # 等价于 CallFSA("myRule")
```

| 参数 | 类型 | 说明 |
|------|------|------|
| `fsaName` | `str` | FSA 规则名称 |
| `**Others` | 关键字参数 | FSA 参数，自动拼接为 `"Key1=Val1;Key2=Val2"` 格式 |

**返回值**：`int`，FSA 执行结果长度。

**说明**：FSA 匹配成功后，会通过 `exec()` 执行规则中嵌入的 Python 代码。

#### `GetFSAParam(key)` / `GetParam(key)`

获取 FSA 参数。

```python
val = gpf.GetFSAParam("key")
val = gpf.GetParam("key")    # 等价
```

**返回值**：`str`，参数值。

#### `GetFSANode(tag="-1")` / `GetNode(tag)`

获取 FSA 节点。

```python
pathNo = gpf.GetFSANode("tag")  # 按标签获取
pathNo = gpf.GetNode(0)         # 按整数标签获取（自动转字符串）
```

**返回值**：`int`，路径号。

### 4.10 索引创建

#### `IndexTable(table_filename)`

索引 Table 文件。

```python
gpf.IndexTable("./data/myTable.txt")
```

| 参数 | 类型 | 说明 |
|------|------|------|
| `table_filename` | `str` | Table 文件路径 |

**返回值**：若存在搭配（Collocation）信息，返回 `dict`（搭配数据）；否则返回 `0`。

**说明**：索引完成后自动调用 `GPF_ReLoad` 重新加载配置。若存在搭配关系，会递归索引搭配表。

#### `IndexFSA(rule_filename)`

索引 FSA 规则文件。

```python
gpf.IndexFSA("./data/myRule.txt")
```

| 参数 | 类型 | 说明 |
|------|------|------|
| `rule_filename` | `str` | FSA 规则文件路径 |

**返回值**：`int`，操作状态码。

### 4.11 服务调用与 Dot 可视化

#### `CallService(sentence, name)`

调用远程服务进行文本解析。

```python
result = gpf.CallService("自然语言处理", "Tree")
```

| 参数 | 类型 | 说明 |
|------|------|------|
| `sentence` | `str` | 输入文本 |
| `name` | `str` | 服务名称 |

**返回值**：`str`，服务返回的 JSON 字符串。

#### `Dot2Img(Dot, name)`

将 Dot 脚本转换为图片（通过 DLL）。

```python
img = gpf.Dot2Img(dot_string, "myGraph")
```

**返回值**：`bytes`，图片数据。

#### `DotFile(dot_filename, img_filename)`

将 Dot 文件通过远程服务转换为图片文件。

```python
gpf.DotFile("graph.dot", "graph.png")
```

**返回值**：`bool`，成功返回 `True`。

#### `DotBuff(dot_data, img_filename)`

将 Dot 字符串通过远程服务转换为图片文件。

```python
gpf.DotBuff(dot_string, "graph.png")
```

**返回值**：`bool`，成功返回 `True`。

### 4.12 结构添加

将 JSON 格式的语言结构数据添加到当前网格中。

#### `AddStructure(json_str)` / `AddGrid(json_str)` / `AddGridJS(json_str)`

添加结构，自动识别类型。

```python
gpf.AddStructure(json_str)
gpf.AddGrid(json_str)      # 等价
gpf.AddGridJS(json_str)    # 等价
```

**说明**：根据 JSON 结构自动判断类型：
- 若 JSON 包含 `"Type"` 字段：直接调用 `GPF_AddStructure`
- 否则自动识别为 Graph / Seq / Tree，调用对应的添加方法

#### `AddSeq(json_str)`

添加序列结构（如分词结果）。

```python
# 字符串列表格式
gpf.AddSeq('["自然/b", "语言/n", "处理/v"]')

# 字典列表格式（带属性）
gpf.AddSeq('[{"自然": {"POS": "b"}}, {"语言": {"POS": "n"}}]')
```

**支持的 JSON 格式**：
- 字符串列表：`["词1", "词1/POS", ...]`
- 字典列表：`[{"词": {"属性名": "属性值"}}, ...]`，或包含 `"Unit"` 和 `"Att"` 字段的字典

#### `AddTree(json_str)`

添加树结构。

```python
gpf.AddTree('{"S": ["NP", {"VP": ["V", "NP"]}]}')
```

**说明**：将 JSON 的括号语法转换为 `"Type":"Tree"` 格式后调用 `AddGridJS`。

#### `AddGraph(json_str)`

添加图结构（有向图）。

```python
# 三元组列表格式：[源, 目标, 关系]
gpf.AddGraph('[["喜欢", "我", "SBJ"], ["喜欢", "北京", "OBJ"]]')

# 字典格式：{源: {关系: 目标}}
gpf.AddGraph('{"喜欢": {"SBJ": "我", "OBJ": "北京"}}')
```

#### `Add2Grid(Txt, Head, Tail, Rel)`

底层方法，向网格中添加一条边（两个 Unit + 关系）。

```python
gpf.Add2Grid("我喜欢北京", "喜欢", "我", "SBJ")
```

### 4.13 可视化输出

GPF 提供多种可视化方法，生成 Graphviz DOT 脚本或 PNG 图片。

#### `Show(Json="", **Others)`

统一可视化接口。

```python
gpf.Show()                                  # 显示当前网格
gpf.Show(Json=json_str)                     # 显示 JSON 结构
gpf.Show(Output="output.png")               # 指定输出文件
gpf.Show(Relation=True)                     # 显示关系
gpf.Show(Grid=False, Relation=True)         # 只显示关系，不显示网格
gpf.Show(Unit=unitNo)                       # 显示单个 Unit 的属性
```

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `Json` | `str` | `""` | JSON 结构数据 |
| `Output` | `str` | `"./gpf.png"` | 输出图片路径 |
| `Relation` / `IsShowRelation` | `bool` | `False` | 是否显示关系 |
| `Grid` / `IsShowGrid` | `bool` | `True` | 是否显示网格 |
| `Unit` | `str` | `""` | 显示指定 Unit 的详情 |

#### `ShowStructure(Json="", Img="./gpf.png")`

显示结构（自动识别类型并调用对应的可视化方法）。

```python
gpf.ShowStructure(json_str, "output.png")
```

#### `ShowGrid(Img="./gpf.png", IsShowRel=False, IsShowGrid=True)`

显示网格结构。

```python
gpf.ShowGrid("output.png")                          # 仅网格
gpf.ShowGrid("output.png", IsShowRel=True)           # 网格 + 关系
gpf.ShowGrid("output.png", IsShowRel=True, IsShowGrid=False)  # 仅关系
```

**说明**：网格中的 Unit 按类型着色：
- `Type=Char`：灰色
- `Type=Word`：绿色
- `Type=Phrase`：浅蓝色
- `Type=Chunk`：金色

#### `ShowUnit(Unit, Img="./gpf.png")`

显示单个 Unit 的属性详情图。

```python
gpf.ShowUnit(unitNo, "unit_detail.png")
```

#### `ShowRelation(Img="./gpf.png")`

显示关系图（等价于 `ShowGrid(Img, IsShowRel=True, IsShowGrid=True)`）。

```python
gpf.ShowRelation("relations.png")
```

#### `ShowTree(Json)` / `ShowSeq(Json)` / `ShowGraph(Json)`

返回 DOT 脚本字符串（不直接生成文件）。

```python
dot = gpf.ShowTree(json_str)    # 树结构 DOT（自上而下排列）
dot = gpf.ShowSeq(json_str)     # 序列结构 DOT（从左到右排列）
dot = gpf.ShowGraph(json_str)   # 图结构 DOT
```

**返回值**：`str`，Graphviz DOT 脚本。

#### `ShowCloud(Json, Output)`

生成词云图片。

```python
gpf.ShowCloud('{"自然": 10, "语言": 8, "处理": 6}', "cloud.png")
```

| 参数 | 类型 | 说明 |
|------|------|------|
| `Json` | `str` | JSON 格式的词频数据 `{"词": 频率, ...}` |
| `Output` | `str` | 输出图片路径 |

### 4.14 其他方法

#### `GetLog()`

获取 GPF 日志。

```python
log = gpf.GetLog()
```

**返回值**：`dict`，日志信息。

#### `Reduce(From=0, To=-1, Head=-1)`

归约操作，将指定范围的 Unit 归约为一个新 Unit。

```python
unitNo = gpf.Reduce(From=0, To=5, Head=0)
```

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `From` | `int` | `0` | 归约起始位置 |
| `To` | `int` | `-1` | 归约结束位置 |
| `Head` | `int` | `-1` | 中心词的 FSA 路径号 |

**返回值**：`str`，新 Unit 编号。

#### `GPFInit()`

手动初始化 GPF 数据（线程安全）。通常无需显式调用，GPF 方法内部会自动调用。

```python
gpf.GPFInit()
```

#### `GPFPersons()`

致谢信息。

### 4.15 GPF 方法速查表

| 分类 | 方法 | 说明 |
|------|------|------|
| **NLP** | `Segment(text, table)` | CRF 分词 |
| | `POS(text, table)` | 词性标注 |
| | `Parse(text, **Others)` | 统一解析接口 |
| **文本** | `SetText(text)` / `SetGridText(text)` | 设置文本 |
| | `GetText(begin, end)` / `GetGridText(begin, end)` | 获取文本 |
| | `GetGrid()` / `GetStructure()` | 获取网格结构 |
| **Unit** | `AddUnit(text, colNo)` | 添加 Unit |
| | `AddUnitKV(unitNo, key, val)` | 添加 Unit 属性 |
| | `GetWord(unitNo)` | 获取 Unit 文本 |
| | `GetUnit(kv)` / `GetUnits(kv)` | 查找 Unit |
| | `GetUnitKV(unitNo, key)` / `GetUnitKVs(unitNo, key)` | 获取 Unit 属性 |
| | `GetFSAUnit(pathNo)` | 按路径号获取 Unit |
| | `IsUnit(unitNo, kv)` | 判断 Unit 属性 |
| **Relation** | `AddRelation(u1, u2, role)` | 添加关系 |
| | `AddRelationKV(u1, u2, role, key, val)` | 添加关系属性 |
| | `GetRelation(kv)` / `GetRelations(kv)` | 获取关系 |
| | `GetRelationKV(u1, u2, role, key)` / `GetRelationKVs(...)` | 获取关系属性 |
| | `IsRelation(u1, u2, role, kv)` | 判断关系 |
| **Grid KV** | `AddGridKV(key, val)` / `AddTextKV(key, val)` | 添加网格属性 |
| | `GetGridKV(key)` / `GetGridKVs(key)` / `GetTextKV(key)` | 获取网格属性 |
| **Table** | `SetTable(tableName)` | 设置当前表 |
| | `CallTable(tableName)` | 加载并设置表 |
| | `GetTable()` | 获取所有表名 |
| | `GetTableItem(tableName, kv)` / `GetItem(...)` | 获取表条目 |
| | `GetTableItems(tableName, kv)` | 获取表条目（带过滤） |
| | `GetTableItemKV(...)` / `GetItemKV(...)` / `GetTableItemKVs(...)` | 获取条目属性 |
| | `IsTable(tableName, item, kv)` | 判断表/条目/属性 |
| | `GetSuffix(tableName, sentence)` | 后缀匹配 |
| | `GetPrefix(tableName, sentence)` | 前缀匹配 |
| **FSA** | `CallFSA(fsaName, **Others)` / `RunFSA(fsaName)` | 执行 FSA |
| | `GetFSAParam(key)` / `GetParam(key)` | 获取 FSA 参数 |
| | `GetFSANode(tag)` / `GetNode(tag)` | 获取 FSA 节点 |
| **索引** | `IndexTable(filename)` | 索引 Table 文件 |
| | `IndexFSA(filename)` | 索引 FSA 文件 |
| **服务** | `CallService(sentence, name)` | 调用远程服务 |
| | `Dot2Img(dot, name)` | Dot 转图片 |
| | `DotFile(dot_file, img_file)` | Dot 文件转图片 |
| | `DotBuff(dot_data, img_file)` | Dot 字符串转图片 |
| **结构添加** | `AddStructure(json)` / `AddGrid(json)` / `AddGridJS(json)` | 添加结构 |
| | `AddSeq(json)` | 添加序列 |
| | `AddTree(json)` | 添加树 |
| | `AddGraph(json)` | 添加图 |
| **可视化** | `Show(Json, **Others)` | 统一可视化 |
| | `ShowStructure(Json, Img)` | 显示结构 |
| | `ShowGrid(Img, IsShowRel, IsShowGrid)` | 显示网格 |
| | `ShowUnit(Unit, Img)` | 显示 Unit 详情 |
| | `ShowRelation(Img)` | 显示关系图 |
| | `ShowTree(Json)` / `ShowSeq(Json)` / `ShowGraph(Json)` | 返回 DOT 脚本 |
| | `ShowCloud(Json, Output)` | 词云 |
| **其他** | `GetLog()` | 获取日志 |
| | `Reduce(From, To, Head)` | 归约操作 |
| | `GPFInit()` | 手动初始化 |

---

## 5. BCC 类 — 语料库查询

BCC（BCC Corpus）提供语料库查询功能，支持词频统计、上下文检索和语料索引。

### 5.1 构造函数与初始化

```python
from LangSC import BCC

bcc = BCC(dataPath="./data")
```

**参数**

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `dataPath` | `str` | `"./data"` | 语料数据目录路径 |

**说明**
- 构造函数自动加载 `bcclib` 动态库
- 自动加载 BCC 配置文件（`BCCconfig.txt`）和 Lua 解析脚本（`Parser.lua`）
- 自动检测并索引语料数据（详见 [5.2 自动索引机制](#52-自动索引机制)）

### 5.2 自动索引机制

构造函数调用 `_init_bcc_data(dataPath)` 自动处理语料索引：

1. 检查 `dataPath` 中是否存在 `IdxLog_BCC.txt`
2. **若存在**：已是索引目录，直接使用
3. **若不存在**：视为原始语料目录
   - 扫描目录下的语料文件（排除 Table 和 FSA 格式）
   - 检查 `dataPathIdx/` 是否存在且时间戳一致（避免重复索引）
   - 若需要索引，调用 `IndexBCC` 对所有语料文件建索引
   - 写入 `IdxLog_BCC.txt` 索引日志

### 5.3 语料查询

#### `CallBCC(query)`

执行原始 BCC 查询语句。

```python
result = bcc.CallBCC("学习{}Freq(100,$Q,0)")
result = bcc.CallBCC("学习{}Context(20,0,100)")
result = bcc.CallBCC("学习{}Count()")
```

| 参数 | 类型 | 说明 |
|------|------|------|
| `query` | `str` | BCC 查询语句 |

**返回值**：`str`，查询结果（JSON 格式字符串）。

**查询语句格式**：`查询词{}操作(参数)`
- `Freq(数量, 目标字段, 上下文条数)` — 词频统计
- `Context(窗口大小, 页码, 条数)` — 上下文检索
- `Count()` — 计数统计

**说明**
- 首次调用时自动初始化 BCC 引擎（线程安全）
- 若初始化失败且查询不含 "Lua"，返回 `{}`

#### `RunBCC(Query, **Others)`

高级查询接口，通过关键字参数构造查询语句。

```python
# 词频查询（默认）
result = bcc.RunBCC("学习")

# 指定查询模式和参数
result = bcc.RunBCC("学习", Command="Freq", Number=200)
result = bcc.RunBCC("学习", Command="Context", WinSize=30, Number=100)
result = bcc.RunBCC("学习", Command="Count")

# 带逻辑运算
result = bcc.RunBCC("学习 AND 方法", Command="Freq")
result = bcc.RunBCC("学习 NOT 机器", Command="Freq")

# Lua 格式输出
result = bcc.RunBCC("学习", Command="Freq", Print="Lua")
```

**完整参数列表**

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `Query` | `str` | （必填） | 查询词或查询表达式 |
| `Command` / `Output` | `str` | `"Freq"` | 查询模式：`"Freq"` / `"Context"` / `"Count"` 或自定义命令 |
| `Number` | `int` | `100` | 返回条数上限 |
| `Target` | `str` | `"$Q"` | 目标字段标识符 |
| `WinSize` | `int` | `20` | 上下文窗口大小（`Context` 模式） |
| `PageNo` | `int` | `0` | 分页页码（`Context` 模式） |
| `Print` | `str` | `""` | 输出格式，`"Lua"` 为 Lua 脚本格式 |
| `Speedup` | `int` | `1` | 加速选项 |
| `ContextNum` | `int` | `0` | 上下文条数（`Freq` 模式附带上下文） |

**返回值**：`str`，查询结果。

**查询语句自动生成规则**：
- 若 `Query` 不含 `{}`，自动追加 `{}`
- `Freq` 模式生成：`Query{}Freq(Number, Target, ContextNum)`
- `Context` 模式生成：`Query{}Context(WinSize, PageNo, Number)`
- `Count` 模式生成：`Query{}Count()`
- `AND` / `NOT` 运算符会在运算符位置插入操作

### 5.4 KV 操作

BCC 引擎维护一个全局键值存储，可在查询间传递上下文信息。

#### `AddBCCKV(Key, Val)`

添加键值对。

```python
bcc.AddBCCKV("Filter", "新闻")
bcc.AddBCCKV("Tags", "人名;地名;机构名")  # 多值用分隔符
```

| 参数 | 类型 | 说明 |
|------|------|------|
| `Key` | `str` | 键名 |
| `Val` | `str` | 值（支持以空格、分号、逗号、制表符分隔的多值，会合并为分号分隔） |

**返回值**：`str`，操作结果。

#### `GetBCCKV(Key="")` / `GetBCCKVs(Key="")`

获取键值。

```python
val = bcc.GetBCCKV("Filter")     # 获取指定键
all_kvs = bcc.GetBCCKV()         # 获取全部键值
all_kvs = bcc.GetBCCKVs()        # 等价
```

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `Key` | `str` | `""` | 键名（为空返回全部） |

**返回值**：`str`，查询结果。

#### `ClearBCCKV(Key="")`

清空键值存储。

```python
bcc.ClearBCCKV()
```

**返回值**：`str`，操作结果。

### 5.5 语料索引

#### `IndexBCC(filelistname, **Others)`

索引语料文件，支持多种输入格式。

```python
# 1. 索引整个目录（递归扫描）
bcc.IndexBCC("/path/to/corpus_dir")

# 2. 索引文件列表文件（每行一个文件路径）
bcc.IndexBCC("/path/to/filelist.txt")

# 3. 索引单个文件
bcc.IndexBCC("/path/to/corpus.txt")

# 4. 索引 Python 列表
bcc.IndexBCC(["file1.txt", "file2.txt", "file3.txt"])

# 5. 指定索引结构
bcc.IndexBCC("/path/to/corpus", Structure="Segment")
bcc.IndexBCC("/path/to/corpus", Structure="HZ")
```

| 参数 | 类型 | 说明 |
|------|------|------|
| `filelistname` | `str` 或 `list` | 语料来源：目录路径、文件列表路径、单个文件路径或 Python 文件路径列表 |
| `Structure` | `str` | 索引结构：`"HZ"`（默认，按汉字）、`"Segment"`（按分词） |

**返回值**：`int`，操作状态码。

**处理流程**：
1. 若输入为目录：递归收集所有文件路径
2. 若输入为文件列表：直接读取
3. 若输入为 Python 列表：写入临时文件
4. 对每个文件检测是否为原始文本（非 Table/Doc 格式），若是则预处理为 Doc 格式
5. 检测文件编码，非 GBK 编码的文件自动转换
6. 调用 `BCC_IndexBCC` 构建索引

### 5.6 BCC 方法速查表

| 方法 | 说明 |
|------|------|
| `CallBCC(query)` | 执行原始查询 |
| `RunBCC(Query, **Others)` | 高级查询接口 |
| `AddBCCKV(Key, Val)` | 添加键值 |
| `GetBCCKV(Key)` / `GetBCCKVs(Key)` | 获取键值 |
| `ClearBCCKV()` | 清空键值 |
| `IndexBCC(filelistname, **Others)` | 索引语料 |

---

## 6. JSS 类 — JSON 结构检索

JSS（JSON Structure Search）提供对 JSON 格式数据的结构化检索能力，支持 SQL 风格查询语法和多表管理。

### 6.1 构造函数与初始化

```python
from LangSC import JSS

jss = JSS(dataPath, log_level=0, log_filename='')
```

**参数**

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `dataPath` | `str` | （必填） | 数据目录路径 |
| `log_level` | `int` | `0` | 日志级别（0=关闭） |
| `log_filename` | `str` | `""` | 日志文件路径（空字符串=不写日志） |

**说明**
- 构造函数自动加载 `jsslib` 动态库
- 使用 10MB 缓冲区（`1024 * 1024 * 10` 字节）
- 支持同时管理多个表，通过 `self.handles` 字典存储
- 析构函数（`__del__`）自动调用 `Terminate()` 释放资源，并卸载 DLL

### 6.2 自动索引机制

构造函数调用 `_init_jss_data(dataPath)` 自动处理索引：

```
步骤 1: 检查 dataPath/IdxLog_JSS.txt
         ├── 存在 → 已是索引目录 → 加载全部子目录中的表 → 完成
         └── 不存在 → 步骤 2

步骤 2: 扫描 dataPath 中的文件
         ├── 无文件 → 完成
         └── 有文件