semantica-graph-sdk 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. semantica_graph_sdk-0.1.0/PKG-INFO +164 -0
  2. semantica_graph_sdk-0.1.0/README.md +153 -0
  3. semantica_graph_sdk-0.1.0/pyproject.toml +28 -0
  4. semantica_graph_sdk-0.1.0/semantica_graph_sdk/__init__.py +110 -0
  5. semantica_graph_sdk-0.1.0/semantica_graph_sdk/_bootstrap.py +71 -0
  6. semantica_graph_sdk-0.1.0/semantica_graph_sdk/_version.py +1 -0
  7. semantica_graph_sdk-0.1.0/semantica_graph_sdk/async_client.py +371 -0
  8. semantica_graph_sdk-0.1.0/semantica_graph_sdk/client.py +403 -0
  9. semantica_graph_sdk-0.1.0/semantica_graph_sdk/envelope.py +39 -0
  10. semantica_graph_sdk-0.1.0/semantica_graph_sdk/errors.py +80 -0
  11. semantica_graph_sdk-0.1.0/semantica_graph_sdk/headers.py +57 -0
  12. semantica_graph_sdk-0.1.0/semantica_graph_sdk/models/__init__.py +3 -0
  13. semantica_graph_sdk-0.1.0/semantica_graph_sdk/models/graph.py +1194 -0
  14. semantica_graph_sdk-0.1.0/semantica_graph_sdk/trace.py +20 -0
  15. semantica_graph_sdk-0.1.0/semantica_graph_sdk/transport.py +227 -0
  16. semantica_graph_sdk-0.1.0/semantica_graph_sdk/transport_async.py +166 -0
  17. semantica_graph_sdk-0.1.0/semantica_graph_sdk.egg-info/PKG-INFO +164 -0
  18. semantica_graph_sdk-0.1.0/semantica_graph_sdk.egg-info/SOURCES.txt +42 -0
  19. semantica_graph_sdk-0.1.0/semantica_graph_sdk.egg-info/dependency_links.txt +1 -0
  20. semantica_graph_sdk-0.1.0/semantica_graph_sdk.egg-info/requires.txt +5 -0
  21. semantica_graph_sdk-0.1.0/semantica_graph_sdk.egg-info/top_level.txt +1 -0
  22. semantica_graph_sdk-0.1.0/setup.cfg +4 -0
  23. semantica_graph_sdk-0.1.0/tests/test_async.py +118 -0
  24. semantica_graph_sdk-0.1.0/tests/test_bootstrap.py +57 -0
  25. semantica_graph_sdk-0.1.0/tests/test_client.py +252 -0
  26. semantica_graph_sdk-0.1.0/tests/test_envelope.py +38 -0
  27. semantica_graph_sdk-0.1.0/tests/test_errors.py +48 -0
  28. semantica_graph_sdk-0.1.0/tests/test_headers.py +36 -0
  29. semantica_graph_sdk-0.1.0/tests/test_models.py +278 -0
  30. semantica_graph_sdk-0.1.0/tests/test_sdk_binding.py +105 -0
  31. semantica_graph_sdk-0.1.0/tests/test_trace.py +19 -0
@@ -0,0 +1,164 @@
1
+ Metadata-Version: 2.4
2
+ Name: semantica-graph-sdk
3
+ Version: 0.1.0
4
+ Summary: Semantica Graph Engine 独立承载服务应用集成 SDK(图谱 CRUD / 建图合并 / 查询分析 / RDF 导出与 SPARQL / 异步任务)
5
+ Requires-Python: >=3.12
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: httpx<1.0,>=0.27
8
+ Requires-Dist: ikc-sdk-lib==0.7.0
9
+ Provides-Extra: dev
10
+ Requires-Dist: pytest>=8.0; extra == "dev"
11
+
12
+ # semantica-graph-sdk
13
+
14
+ Semantica Graph Engine **独立承载服务**(图引擎作为独立进程/容器对外提供)的应用集成 SDK。**v0.1.0**,
15
+ 依赖 `httpx`(传输)与 `ikc-sdk-lib==0.7.0`(图谱资产 DTO 的形状单一来源:`EntityView`/`RelationView`/
16
+ `GraphPageResult`/`EngineJobView` 等),与主包 `graph-engine`(服务端)解耦、不 import 服务端模块。
17
+
18
+ DTO 经 sdk 模型校验后序列化:分页壳含 `totalPages`;作业对象 `status` 为引擎本地态,`taskStatus` 为
19
+ 映射后的外部态(`SUCCEEDED`/`FAILED`…,未知态 fail-closed=FAILED);`JobData.finished` 按外部态终态判定。
20
+
21
+ 设计文档:`docs/独立承载服务与SDK集成设计.md`(仓库根目录)。
22
+
23
+ ## 安装
24
+
25
+ ```bash
26
+ pip install semantica-graph-sdk
27
+ ```
28
+
29
+ 本地开发调试可 `pip install sdk/python`,测试依赖 `pytest`(`pip install "sdk/python[dev]"`)。
30
+
31
+ ## 快速开始(同步)
32
+
33
+ ```python
34
+ from semantica_graph_sdk import GraphEngineClient
35
+
36
+ client = GraphEngineClient(
37
+ base_url="http://127.0.0.1:18010", # 独立承载服务地址(本地 serve / Docker 入口 18180)
38
+ token="<TOKEN>", # 可选;服务端启用鉴权/网关注入时使用
39
+ )
40
+
41
+ # 1. 创建图谱(graphSchema 校验由服务端执行)
42
+ graph = client.graphs.create(
43
+ kbId="kb_demo",
44
+ name="产品知识图谱",
45
+ graphSchema={
46
+ "entityTypes": [{"type": "person"}, {"type": "org"}],
47
+ "relationTypes": [{"type": "works_at", "sourceTypes": ["person"], "targetTypes": ["org"]}],
48
+ },
49
+ )
50
+
51
+ # 2. 建图:记录建图(稳定 ID + 证据 + 置信度)或文本建图
52
+ client.graphs.build(
53
+ graph.graphId,
54
+ docId="doc_1",
55
+ entities=[{"name": "Alice", "type": "person"}, {"name": "Acme", "type": "org"}],
56
+ relations=[{"type": "works_at", "sourceEntityId": "ent_a", "targetEntityId": "ent_b"}],
57
+ )
58
+ built = client.graphs.build(graph.graphId, docId="doc_2", title="手册", text="「Alice」加入「Acme」")
59
+ print(built.entityCount, built.semantica.semantica)
60
+
61
+ # 3. 查询 / 分析 / 导出 / SPARQL / 语义检索
62
+ stat = client.graphs.stat(graph.graphId)
63
+ nodes = client.graphs.nodes(graph.graphId, entityType="person", pageSize=50)
64
+ edges = client.graphs.edges(graph.graphId, relationType="works_at")
65
+ neighbors = client.graphs.neighbors(graph.graphId, entityId=nodes.items[0].entityId, depth=1)
66
+ paths = client.graphs.paths(graph.graphId, sourceEntityId="ent_a", targetEntityId="ent_b", maxDepth=3)
67
+ analytics = client.graphs.analytics(graph.graphId)
68
+ export = client.graphs.export(graph.graphId, format="turtle")
69
+ sparql = client.graphs.sparql(graph.graphId, query="SELECT ?s ?p ?o WHERE { ?s ?p ?o } LIMIT 5")
70
+ search = client.graphs.search(graph.graphId, query="Alice 在哪工作", topK=5)
71
+ print(stat.schemaCoverage.overall, len(sparql.bindings), search.semantica)
72
+
73
+ # 4. 异步任务(async_=True 登记 job;Celery 未启用时可手动执行或轮询)
74
+ job = client.graphs.build(graph.graphId, text="「异步」", async_=True)
75
+ job = client.jobs.run(job.jobId) # 或 client.jobs.wait(job.jobId)
76
+ print(job.status, job.result)
77
+
78
+ client.close()
79
+ ```
80
+
81
+ ## 异步客户端
82
+
83
+ ```python
84
+ import asyncio
85
+ from semantica_graph_sdk import AsyncGraphEngineClient
86
+
87
+ async def main():
88
+ async with AsyncGraphEngineClient(base_url="http://127.0.0.1:18010") as client:
89
+ graph = await client.graphs.create(kbId="kb_async", name="异步示例")
90
+ stat = await client.graphs.stat(graph.graphId)
91
+ print(stat.nodeCount)
92
+
93
+ asyncio.run(main())
94
+ ```
95
+
96
+ 同步与异步客户端共享同一套模型与错误映射;`request`/`raw`/`fetch_openapi`/`health` 低层调用与重试语义一致。
97
+
98
+ ## 环境变量引导
99
+
100
+ ```bash
101
+ export SEMANTICA_GRAPH_BASE_URL=http://127.0.0.1:18010
102
+ export SEMANTICA_GRAPH_TOKEN=<token> # 可选
103
+ export SEMANTICA_GRAPH_USER_ID=u1 # 可选,身份头 X-User-Id,并作为 ownerId 默认值
104
+ export SEMANTICA_GRAPH_TENANT_ID=t1 # 可选,身份头 X-Tenant-Id,并作为 tenantId 默认值
105
+ export SEMANTICA_GRAPH_ROLES=km_admin,viewer # 可选,身份头 X-User-Roles
106
+ ```
107
+
108
+ ```python
109
+ from semantica_graph_sdk import client_from_env, async_client_from_env
110
+
111
+ client = client_from_env() # 等价:GraphEngineClient(base_url=os.environ["SEMANTICA_GRAPH_BASE_URL"], ...)
112
+ ```
113
+
114
+ `CallerIdentity` 的 `tenant_id`/`user_id` 会在请求缺省时补齐 `tenantId`/`ownerId`
115
+ (图引擎的租户/归属是请求参数),显式入参始终优先。
116
+
117
+ ## 领域方法总览
118
+
119
+ - `client.graphs`:`create / list / get / delete / build / merge / deprecate_doc / stat / nodes / edges /
120
+ neighbors / paths / analytics / export / sparql / search / index_status`
121
+ - `client.jobs`:`run / get / list / wait`
122
+ - 低层:`request(method, path, ...)` / `raw(...)`(不抛业务异常)/ `fetch_openapi()` / `health()`
123
+
124
+ ## 异常层级
125
+
126
+ ```
127
+ GraphEngineError
128
+ ├── GraphEngineTransportError # 传输层(含 traceId)
129
+ │ ├── GraphEngineConnectionError
130
+ │ ├── GraphEngineTimeoutError
131
+ │ ├── GraphEngineProtocolError # 响应不符统一壳协议
132
+ │ └── GraphEngineHTTPStatusError # 非 2xx 且非统一壳
133
+ └── GraphEngineAPIError # 业务异常(errCode/errMsg/traceId)
134
+ ├── GraphEngineValidationError # 200001 参数非法
135
+ ├── GraphEngineNotFoundError # 200404 资源不存在
136
+ ├── GraphEngineConflictError # 200409 冲突
137
+ ├── GraphEngineSystemError # 200500 系统错误
138
+ └── GraphEngineBusinessError # 其他错误码兜底
139
+ ```
140
+
141
+ ## 联调冒烟
142
+
143
+ 先启动独立承载服务:
144
+
145
+ ```bash
146
+ graph-engine serve http # 默认 18010
147
+ # 或 docker compose up -d # 单镜像栈入口 18180(HTTP)/ 18151(gRPC)
148
+ ```
149
+
150
+ ```bash
151
+ # 同步全链路:健康检查 → 建图 → 查询/分析/导出/检索 → 异步任务 → 清理
152
+ python sdk/python/examples/quickstart.py
153
+
154
+ # 异步客户端示例
155
+ python sdk/python/examples/async_quickstart.py
156
+ ```
157
+
158
+ ## 自测
159
+
160
+ ```bash
161
+ cd sdk/python && PYTHONPATH=. python -m pytest tests -q
162
+ ```
163
+
164
+ > 测试基于 `httpx.MockTransport`,无需起真实服务。
@@ -0,0 +1,153 @@
1
+ # semantica-graph-sdk
2
+
3
+ Semantica Graph Engine **独立承载服务**(图引擎作为独立进程/容器对外提供)的应用集成 SDK。**v0.1.0**,
4
+ 依赖 `httpx`(传输)与 `ikc-sdk-lib==0.7.0`(图谱资产 DTO 的形状单一来源:`EntityView`/`RelationView`/
5
+ `GraphPageResult`/`EngineJobView` 等),与主包 `graph-engine`(服务端)解耦、不 import 服务端模块。
6
+
7
+ DTO 经 sdk 模型校验后序列化:分页壳含 `totalPages`;作业对象 `status` 为引擎本地态,`taskStatus` 为
8
+ 映射后的外部态(`SUCCEEDED`/`FAILED`…,未知态 fail-closed=FAILED);`JobData.finished` 按外部态终态判定。
9
+
10
+ 设计文档:`docs/独立承载服务与SDK集成设计.md`(仓库根目录)。
11
+
12
+ ## 安装
13
+
14
+ ```bash
15
+ pip install semantica-graph-sdk
16
+ ```
17
+
18
+ 本地开发调试可 `pip install sdk/python`,测试依赖 `pytest`(`pip install "sdk/python[dev]"`)。
19
+
20
+ ## 快速开始(同步)
21
+
22
+ ```python
23
+ from semantica_graph_sdk import GraphEngineClient
24
+
25
+ client = GraphEngineClient(
26
+ base_url="http://127.0.0.1:18010", # 独立承载服务地址(本地 serve / Docker 入口 18180)
27
+ token="<TOKEN>", # 可选;服务端启用鉴权/网关注入时使用
28
+ )
29
+
30
+ # 1. 创建图谱(graphSchema 校验由服务端执行)
31
+ graph = client.graphs.create(
32
+ kbId="kb_demo",
33
+ name="产品知识图谱",
34
+ graphSchema={
35
+ "entityTypes": [{"type": "person"}, {"type": "org"}],
36
+ "relationTypes": [{"type": "works_at", "sourceTypes": ["person"], "targetTypes": ["org"]}],
37
+ },
38
+ )
39
+
40
+ # 2. 建图:记录建图(稳定 ID + 证据 + 置信度)或文本建图
41
+ client.graphs.build(
42
+ graph.graphId,
43
+ docId="doc_1",
44
+ entities=[{"name": "Alice", "type": "person"}, {"name": "Acme", "type": "org"}],
45
+ relations=[{"type": "works_at", "sourceEntityId": "ent_a", "targetEntityId": "ent_b"}],
46
+ )
47
+ built = client.graphs.build(graph.graphId, docId="doc_2", title="手册", text="「Alice」加入「Acme」")
48
+ print(built.entityCount, built.semantica.semantica)
49
+
50
+ # 3. 查询 / 分析 / 导出 / SPARQL / 语义检索
51
+ stat = client.graphs.stat(graph.graphId)
52
+ nodes = client.graphs.nodes(graph.graphId, entityType="person", pageSize=50)
53
+ edges = client.graphs.edges(graph.graphId, relationType="works_at")
54
+ neighbors = client.graphs.neighbors(graph.graphId, entityId=nodes.items[0].entityId, depth=1)
55
+ paths = client.graphs.paths(graph.graphId, sourceEntityId="ent_a", targetEntityId="ent_b", maxDepth=3)
56
+ analytics = client.graphs.analytics(graph.graphId)
57
+ export = client.graphs.export(graph.graphId, format="turtle")
58
+ sparql = client.graphs.sparql(graph.graphId, query="SELECT ?s ?p ?o WHERE { ?s ?p ?o } LIMIT 5")
59
+ search = client.graphs.search(graph.graphId, query="Alice 在哪工作", topK=5)
60
+ print(stat.schemaCoverage.overall, len(sparql.bindings), search.semantica)
61
+
62
+ # 4. 异步任务(async_=True 登记 job;Celery 未启用时可手动执行或轮询)
63
+ job = client.graphs.build(graph.graphId, text="「异步」", async_=True)
64
+ job = client.jobs.run(job.jobId) # 或 client.jobs.wait(job.jobId)
65
+ print(job.status, job.result)
66
+
67
+ client.close()
68
+ ```
69
+
70
+ ## 异步客户端
71
+
72
+ ```python
73
+ import asyncio
74
+ from semantica_graph_sdk import AsyncGraphEngineClient
75
+
76
+ async def main():
77
+ async with AsyncGraphEngineClient(base_url="http://127.0.0.1:18010") as client:
78
+ graph = await client.graphs.create(kbId="kb_async", name="异步示例")
79
+ stat = await client.graphs.stat(graph.graphId)
80
+ print(stat.nodeCount)
81
+
82
+ asyncio.run(main())
83
+ ```
84
+
85
+ 同步与异步客户端共享同一套模型与错误映射;`request`/`raw`/`fetch_openapi`/`health` 低层调用与重试语义一致。
86
+
87
+ ## 环境变量引导
88
+
89
+ ```bash
90
+ export SEMANTICA_GRAPH_BASE_URL=http://127.0.0.1:18010
91
+ export SEMANTICA_GRAPH_TOKEN=<token> # 可选
92
+ export SEMANTICA_GRAPH_USER_ID=u1 # 可选,身份头 X-User-Id,并作为 ownerId 默认值
93
+ export SEMANTICA_GRAPH_TENANT_ID=t1 # 可选,身份头 X-Tenant-Id,并作为 tenantId 默认值
94
+ export SEMANTICA_GRAPH_ROLES=km_admin,viewer # 可选,身份头 X-User-Roles
95
+ ```
96
+
97
+ ```python
98
+ from semantica_graph_sdk import client_from_env, async_client_from_env
99
+
100
+ client = client_from_env() # 等价:GraphEngineClient(base_url=os.environ["SEMANTICA_GRAPH_BASE_URL"], ...)
101
+ ```
102
+
103
+ `CallerIdentity` 的 `tenant_id`/`user_id` 会在请求缺省时补齐 `tenantId`/`ownerId`
104
+ (图引擎的租户/归属是请求参数),显式入参始终优先。
105
+
106
+ ## 领域方法总览
107
+
108
+ - `client.graphs`:`create / list / get / delete / build / merge / deprecate_doc / stat / nodes / edges /
109
+ neighbors / paths / analytics / export / sparql / search / index_status`
110
+ - `client.jobs`:`run / get / list / wait`
111
+ - 低层:`request(method, path, ...)` / `raw(...)`(不抛业务异常)/ `fetch_openapi()` / `health()`
112
+
113
+ ## 异常层级
114
+
115
+ ```
116
+ GraphEngineError
117
+ ├── GraphEngineTransportError # 传输层(含 traceId)
118
+ │ ├── GraphEngineConnectionError
119
+ │ ├── GraphEngineTimeoutError
120
+ │ ├── GraphEngineProtocolError # 响应不符统一壳协议
121
+ │ └── GraphEngineHTTPStatusError # 非 2xx 且非统一壳
122
+ └── GraphEngineAPIError # 业务异常(errCode/errMsg/traceId)
123
+ ├── GraphEngineValidationError # 200001 参数非法
124
+ ├── GraphEngineNotFoundError # 200404 资源不存在
125
+ ├── GraphEngineConflictError # 200409 冲突
126
+ ├── GraphEngineSystemError # 200500 系统错误
127
+ └── GraphEngineBusinessError # 其他错误码兜底
128
+ ```
129
+
130
+ ## 联调冒烟
131
+
132
+ 先启动独立承载服务:
133
+
134
+ ```bash
135
+ graph-engine serve http # 默认 18010
136
+ # 或 docker compose up -d # 单镜像栈入口 18180(HTTP)/ 18151(gRPC)
137
+ ```
138
+
139
+ ```bash
140
+ # 同步全链路:健康检查 → 建图 → 查询/分析/导出/检索 → 异步任务 → 清理
141
+ python sdk/python/examples/quickstart.py
142
+
143
+ # 异步客户端示例
144
+ python sdk/python/examples/async_quickstart.py
145
+ ```
146
+
147
+ ## 自测
148
+
149
+ ```bash
150
+ cd sdk/python && PYTHONPATH=. python -m pytest tests -q
151
+ ```
152
+
153
+ > 测试基于 `httpx.MockTransport`,无需起真实服务。
@@ -0,0 +1,28 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "semantica-graph-sdk"
7
+ version = "0.1.0"
8
+ description = "Semantica Graph Engine 独立承载服务应用集成 SDK(图谱 CRUD / 建图合并 / 查询分析 / RDF 导出与 SPARQL / 异步任务)"
9
+ readme = "README.md"
10
+ requires-python = ">=3.12"
11
+ dependencies = [
12
+ "httpx>=0.27,<1.0",
13
+ # 跨层共享模型/协议 SDK:图谱资产对象(G8)、traceId 纯函数(G2)、引擎作业视图(G3)
14
+ "ikc-sdk-lib==0.7.0",
15
+ ]
16
+
17
+ [project.optional-dependencies]
18
+ dev = ["pytest>=8.0"]
19
+
20
+ [tool.setuptools]
21
+ package-dir = {"" = "."}
22
+
23
+ [tool.setuptools.packages.find]
24
+ where = ["."]
25
+ include = ["semantica_graph_sdk*"]
26
+
27
+ [tool.pytest.ini_options]
28
+ testpaths = ["tests"]
@@ -0,0 +1,110 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+
5
+ from ._bootstrap import async_client_from_env, client_from_env
6
+ from ._version import __version__
7
+ from .async_client import AsyncGraphClient, AsyncGraphEngineClient, AsyncJobsClient
8
+ from .client import GraphClient, GraphEngineClient, JobsClient
9
+ from .envelope import Envelope
10
+ from .errors import (
11
+ GraphEngineAPIError,
12
+ GraphEngineBusinessError,
13
+ GraphEngineConflictError,
14
+ GraphEngineConnectionError,
15
+ GraphEngineError,
16
+ GraphEngineHTTPStatusError,
17
+ GraphEngineNotFoundError,
18
+ GraphEngineProtocolError,
19
+ GraphEngineSystemError,
20
+ GraphEngineTimeoutError,
21
+ GraphEngineTransportError,
22
+ GraphEngineValidationError,
23
+ exception_from_code,
24
+ )
25
+ from .headers import CallerIdentity, identity_defaults
26
+ from .models.graph import (
27
+ AnalyticsData,
28
+ BuildResult,
29
+ DeleteResult,
30
+ DeprecateResult,
31
+ Entity,
32
+ EntityListData,
33
+ ExportResult,
34
+ GraphListData,
35
+ GraphMeta,
36
+ GraphPath,
37
+ IndexStatusData,
38
+ JobData,
39
+ JobListData,
40
+ NeighborData,
41
+ PathListData,
42
+ Relation,
43
+ RelationListData,
44
+ SchemaCoverage,
45
+ SearchData,
46
+ SearchHit,
47
+ SemanticaMeta,
48
+ SparqlResult,
49
+ StatResult,
50
+ TypeCount,
51
+ )
52
+ from .trace import generate_trace_id
53
+
54
+ __all__ = [
55
+ "GraphEngineClient",
56
+ "AsyncGraphEngineClient",
57
+ "GraphClient",
58
+ "AsyncGraphClient",
59
+ "JobsClient",
60
+ "AsyncJobsClient",
61
+ "client_from_env",
62
+ "async_client_from_env",
63
+ "Envelope",
64
+ "CallerIdentity",
65
+ "identity_defaults",
66
+ "GraphMeta",
67
+ "GraphListData",
68
+ "DeleteResult",
69
+ "SemanticaMeta",
70
+ "BuildResult",
71
+ "DeprecateResult",
72
+ "TypeCount",
73
+ "SchemaCoverage",
74
+ "StatResult",
75
+ "Entity",
76
+ "EntityListData",
77
+ "Relation",
78
+ "RelationListData",
79
+ "NeighborData",
80
+ "GraphPath",
81
+ "PathListData",
82
+ "AnalyticsData",
83
+ "ExportResult",
84
+ "SparqlResult",
85
+ "SearchHit",
86
+ "SearchData",
87
+ "IndexStatusData",
88
+ "JobData",
89
+ "JobListData",
90
+ "generate_trace_id",
91
+ "GraphEngineError",
92
+ "GraphEngineTransportError",
93
+ "GraphEngineConnectionError",
94
+ "GraphEngineTimeoutError",
95
+ "GraphEngineProtocolError",
96
+ "GraphEngineHTTPStatusError",
97
+ "GraphEngineAPIError",
98
+ "GraphEngineValidationError",
99
+ "GraphEngineNotFoundError",
100
+ "GraphEngineConflictError",
101
+ "GraphEngineSystemError",
102
+ "GraphEngineBusinessError",
103
+ "exception_from_code",
104
+ "__version__",
105
+ ]
106
+
107
+
108
+ def set_log_level(level: int | str) -> None:
109
+ """设置 SDK 日志级别(默认 WARNING)。"""
110
+ logging.getLogger("semantica_graph_sdk").setLevel(level)
@@ -0,0 +1,71 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+
5
+ from .async_client import AsyncGraphEngineClient
6
+ from .client import GraphEngineClient
7
+ from .headers import CallerIdentity
8
+
9
+ DEFAULT_BASE_URL = "http://127.0.0.1:18010"
10
+
11
+ _ENV_BASE_URL = "SEMANTICA_GRAPH_BASE_URL"
12
+ _ENV_TOKEN = "SEMANTICA_GRAPH_TOKEN"
13
+ _ENV_USER_ID = "SEMANTICA_GRAPH_USER_ID"
14
+ _ENV_TENANT_ID = "SEMANTICA_GRAPH_TENANT_ID"
15
+ _ENV_ROLES = "SEMANTICA_GRAPH_ROLES"
16
+
17
+
18
+ def _identity_from_env(
19
+ user_id: str | None,
20
+ tenant_id: str | None,
21
+ roles: str | None,
22
+ ) -> CallerIdentity | None:
23
+ """组装身份上下文;所有字段为空时返回 None(不附加身份头、不补齐归属)。"""
24
+ user_id = user_id or os.getenv(_ENV_USER_ID, "").strip()
25
+ tenant_id = tenant_id or os.getenv(_ENV_TENANT_ID, "").strip()
26
+ roles_value = roles or os.getenv(_ENV_ROLES, "").strip()
27
+
28
+ roles_list: list[str] | None = None
29
+ if roles_value:
30
+ roles_list = [item.strip() for item in roles_value.split(",") if item.strip()]
31
+
32
+ if not user_id and not tenant_id and not roles_list:
33
+ return None
34
+ return CallerIdentity(user_id=user_id or None, tenant_id=tenant_id or None, roles=roles_list)
35
+
36
+
37
+ def client_from_env(
38
+ *,
39
+ base_url: str | None = None,
40
+ token: str | None = None,
41
+ user_id: str | None = None,
42
+ tenant_id: str | None = None,
43
+ roles: str | None = None,
44
+ **kwargs,
45
+ ) -> GraphEngineClient:
46
+ """从环境变量 + 显式参数构造同步客户端;显式参数优先。
47
+
48
+ env:SEMANTICA_GRAPH_BASE_URL(默认 http://127.0.0.1:18010)/ SEMANTICA_GRAPH_TOKEN /
49
+ SEMANTICA_GRAPH_USER_ID / SEMANTICA_GRAPH_TENANT_ID / SEMANTICA_GRAPH_ROLES。
50
+ 额外关键字参数(timeout/max_retries/http_client 等)原样透传。
51
+ """
52
+ resolved_base_url = base_url or os.getenv(_ENV_BASE_URL, DEFAULT_BASE_URL)
53
+ resolved_token = token or os.getenv(_ENV_TOKEN, "").strip() or None
54
+ identity = _identity_from_env(user_id, tenant_id, roles)
55
+ return GraphEngineClient(base_url=resolved_base_url, token=resolved_token, identity=identity, **kwargs)
56
+
57
+
58
+ def async_client_from_env(
59
+ *,
60
+ base_url: str | None = None,
61
+ token: str | None = None,
62
+ user_id: str | None = None,
63
+ tenant_id: str | None = None,
64
+ roles: str | None = None,
65
+ **kwargs,
66
+ ) -> AsyncGraphEngineClient:
67
+ """从环境变量 + 显式参数构造异步客户端;语义与 client_from_env 一致。"""
68
+ resolved_base_url = base_url or os.getenv(_ENV_BASE_URL, DEFAULT_BASE_URL)
69
+ resolved_token = token or os.getenv(_ENV_TOKEN, "").strip() or None
70
+ identity = _identity_from_env(user_id, tenant_id, roles)
71
+ return AsyncGraphEngineClient(base_url=resolved_base_url, token=resolved_token, identity=identity, **kwargs)
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"