arize-phoenix 5.1.4__py3-none-any.whl → 5.1.6__py3-none-any.whl

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.

Potentially problematic release.


This version of arize-phoenix might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: arize-phoenix
3
- Version: 5.1.4
3
+ Version: 5.1.6
4
4
  Summary: AI Observability and Evaluation
5
5
  Project-URL: Documentation, https://docs.arize.com/phoenix/
6
6
  Project-URL: Issues, https://github.com/Arize-ai/phoenix/issues
@@ -23,10 +23,10 @@ Requires-Dist: arize-phoenix-evals>=0.13.1
23
23
  Requires-Dist: arize-phoenix-otel>=0.5.1
24
24
  Requires-Dist: authlib
25
25
  Requires-Dist: cachetools
26
+ Requires-Dist: fast-hdbscan>=0.2.0
26
27
  Requires-Dist: fastapi
27
28
  Requires-Dist: grpc-interceptor
28
29
  Requires-Dist: grpcio
29
- Requires-Dist: hdbscan>=0.8.38
30
30
  Requires-Dist: httpx
31
31
  Requires-Dist: jinja2
32
32
  Requires-Dist: numba>=0.60.0
@@ -48,10 +48,9 @@ Requires-Dist: scipy
48
48
  Requires-Dist: sqlalchemy[asyncio]<3,>=2.0.4
49
49
  Requires-Dist: sqlean-py>=3.45.1
50
50
  Requires-Dist: starlette
51
- Requires-Dist: strawberry-graphql==0.236.0
51
+ Requires-Dist: strawberry-graphql==0.243.1
52
52
  Requires-Dist: tqdm
53
- Requires-Dist: typing-extensions>=4.5; python_version < '3.12'
54
- Requires-Dist: typing-extensions>=4.6; python_version >= '3.12'
53
+ Requires-Dist: typing-extensions>=4.6
55
54
  Requires-Dist: umap-learn
56
55
  Requires-Dist: uvicorn
57
56
  Requires-Dist: wrapt
@@ -65,14 +64,14 @@ Requires-Dist: opentelemetry-sdk; extra == 'container'
65
64
  Requires-Dist: opentelemetry-semantic-conventions; extra == 'container'
66
65
  Requires-Dist: prometheus-client; extra == 'container'
67
66
  Requires-Dist: py-grpc-prometheus; extra == 'container'
68
- Requires-Dist: strawberry-graphql[opentelemetry]==0.236.0; extra == 'container'
67
+ Requires-Dist: strawberry-graphql[opentelemetry]==0.243.1; extra == 'container'
69
68
  Requires-Dist: uvloop; (platform_system != 'Windows') and extra == 'container'
70
69
  Provides-Extra: dev
71
70
  Requires-Dist: anthropic; extra == 'dev'
72
71
  Requires-Dist: arize[autoembeddings,llm-evaluation]; extra == 'dev'
73
72
  Requires-Dist: asgi-lifespan; extra == 'dev'
74
73
  Requires-Dist: asyncpg; extra == 'dev'
75
- Requires-Dist: faker>=26.0.0; extra == 'dev'
74
+ Requires-Dist: faker>=30.1.0; extra == 'dev'
76
75
  Requires-Dist: gcsfs; extra == 'dev'
77
76
  Requires-Dist: google-cloud-aiplatform>=1.3; extra == 'dev'
78
77
  Requires-Dist: grpc-interceptor[testing]; extra == 'dev'
@@ -83,8 +82,7 @@ Requires-Dist: litellm>=1.0.3; extra == 'dev'
83
82
  Requires-Dist: llama-index>=0.10.3; extra == 'dev'
84
83
  Requires-Dist: mypy==1.11.2; extra == 'dev'
85
84
  Requires-Dist: nbqa; extra == 'dev'
86
- Requires-Dist: pandas-stubs==2.0.3.230814; (python_version < '3.9') and extra == 'dev'
87
- Requires-Dist: pandas-stubs==2.2.2.240603; (python_version >= '3.9') and extra == 'dev'
85
+ Requires-Dist: pandas-stubs==2.2.2.240603; extra == 'dev'
88
86
  Requires-Dist: pandas>=1.0; extra == 'dev'
89
87
  Requires-Dist: portpicker; extra == 'dev'
90
88
  Requires-Dist: pre-commit; extra == 'dev'
@@ -94,9 +92,9 @@ Requires-Dist: pytest-asyncio; extra == 'dev'
94
92
  Requires-Dist: pytest-cov; extra == 'dev'
95
93
  Requires-Dist: pytest-postgresql; extra == 'dev'
96
94
  Requires-Dist: pytest-xdist; extra == 'dev'
97
- Requires-Dist: pytest==8.3.2; extra == 'dev'
98
- Requires-Dist: ruff==0.6.4; extra == 'dev'
99
- Requires-Dist: strawberry-graphql[debug-server,opentelemetry]==0.236.0; extra == 'dev'
95
+ Requires-Dist: pytest==8.3.3; extra == 'dev'
96
+ Requires-Dist: ruff==0.6.8; extra == 'dev'
97
+ Requires-Dist: strawberry-graphql[debug-server,opentelemetry]==0.243.1; extra == 'dev'
100
98
  Requires-Dist: tabulate; extra == 'dev'
101
99
  Requires-Dist: tox-uv==1.11.3; extra == 'dev'
102
100
  Requires-Dist: tox==4.18.1; extra == 'dev'
@@ -6,7 +6,7 @@ phoenix/exceptions.py,sha256=n2L2KKuecrdflB9MsCdAYCiSEvGJptIsfRkXMoJle7A,169
6
6
  phoenix/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
7
7
  phoenix/services.py,sha256=aTxhcOA1pZHB6U-B3TEcp6fqDF5oT0xCUvEUNMZVTUQ,5175
8
8
  phoenix/settings.py,sha256=ht-0oN-sMV6SPXrk7Tu1EZlngpAYkGNLYPhO8DyrdQI,661
9
- phoenix/version.py,sha256=wQ7GIU7vx8_5kvdxc8_FSLwGCA9W3Ex29OSYU0A5tyo,22
9
+ phoenix/version.py,sha256=Q46Pugq4dvkkf_16U7KgXoGZYZmz7sapzjpUKHTufZ0,22
10
10
  phoenix/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  phoenix/core/embedding_dimension.py,sha256=zKGbcvwOXgLf-yrJBpQyKtd-LEOPRKHnUToyAU8Owis,87
12
12
  phoenix/core/model.py,sha256=km_a--PBHOuA337ClRw9xqhOHhrUT6Rl9pz_zV0JYkQ,4843
@@ -68,12 +68,12 @@ phoenix/metrics/retrieval_metrics.py,sha256=XFQPo66h16w7-1AJ92M1VL_BUIXIWxXHGKF_
68
68
  phoenix/metrics/timeseries.py,sha256=Cib3E0njJzi0vZpmyADvbakFQA98rIkfDaYAOmsmBz8,6277
69
69
  phoenix/metrics/wrappers.py,sha256=umZqa_5lf1wZSFe3FgzxF-qp1xbPdKD54W628GlGCUI,8392
70
70
  phoenix/pointcloud/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
71
- phoenix/pointcloud/clustering.py,sha256=YDX3Cc57yAAvixeMuV0fgoIfgbkwgEVkzYMLOdN8Tko,829
71
+ phoenix/pointcloud/clustering.py,sha256=lU0cDWYFpPRZaHzZw0NAr4Abe2S32XVxwNUhSYAUHsQ,834
72
72
  phoenix/pointcloud/pointcloud.py,sha256=4zAIkKs2xOUbchpj4XDAV-iPMXrfAJ15TG6rlIYGrao,2145
73
73
  phoenix/pointcloud/projectors.py,sha256=TQgwc9cJDjJkin1WZyZzgl3HsYrLLiyWD7Czy4jNW3U,1088
74
74
  phoenix/pointcloud/umap_parameters.py,sha256=3UQSjrysVOvq2V4KNpTMqNqNiK0BsTZnPBHWZ4fyJtQ,1708
75
75
  phoenix/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
76
- phoenix/server/app.py,sha256=V3ltox8-ptAQPpE68YmF39WlfYbaquMmdJ333M_uIiw,31539
76
+ phoenix/server/app.py,sha256=FRauYpuCTsz761ekVqyXL93VkTx_xknFdMP4LqNowIk,31689
77
77
  phoenix/server/bearer_auth.py,sha256=hChZ2li9qqQAuXIFtD4bp7Z60gEZhVqfCCqLeiTvD2k,5513
78
78
  phoenix/server/dml_event.py,sha256=MpjCFqljxvgb9OB5Cez9vJesb3oHb3XxXictynBfcis,2851
79
79
  phoenix/server/dml_event_handler.py,sha256=yU23-DDwXcL35p5EPwFW0oZh6mxQxJrJAQPKcYZYJz4,8310
@@ -258,15 +258,15 @@ phoenix/server/static/apple-touch-icon-76x76.png,sha256=CT_xT12I0u2i0WU8JzBZBuOQ
258
258
  phoenix/server/static/apple-touch-icon.png,sha256=fOfpjqGpWYbJ0eAurKsyoZP1EAs6ZVooBJ_SGk2ZkDs,3801
259
259
  phoenix/server/static/favicon.ico,sha256=bY0vvCKRftemZfPShwZtE93DiiQdaYaozkPGwNFr6H8,34494
260
260
  phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_wcU9c,2564
261
- phoenix/server/static/.vite/manifest.json,sha256=m-L41ESalPUFFiNXV5MXzbjrXvWRe0EGb4OYPZiMiS4,1929
262
- phoenix/server/static/assets/components-rP68rA45.js,sha256=09AjciFfDrLsdvf664-0OWZMl4w5Da9SZ9wrCdsyOk4,260149
263
- phoenix/server/static/assets/index-CHLTxqHu.js,sha256=Eq7C2V8KWJYa50N80IlfHHxwq3MgmJy8CIDNfGXo04Y,6947
264
- phoenix/server/static/assets/pages-gwtz6mex.js,sha256=pXDio_UYT8pRWwSONS8kNFIbCRaacVP8ZiUiTXZ4Tj0,557771
265
- phoenix/server/static/assets/vendor-D8cj1ZYg.js,sha256=UeDWj3xjmDOo7XvqugE_ePbZZG_o1X6QqdB2Jop7dPs,1435307
261
+ phoenix/server/static/.vite/manifest.json,sha256=tQOBj8Iziu2DVq_Qj9IU_om1c2kmc0GLIfXZavtRRtc,1929
262
+ phoenix/server/static/assets/components-4ANbS7sG.js,sha256=f_MB3rIgNxVf7Hd-EfJ0EmOUuO5YMlvY05YAgOESh0o,260281
263
+ phoenix/server/static/assets/index-CwRlD2_T.js,sha256=KD4j4pJgjb5mJSxUlHk8bclgDIFLK6cRWvyLnHAAmHY,6947
264
+ phoenix/server/static/assets/pages-IkQNKgib.js,sha256=I3jikb9Up6d6DSZXu6hDOUnJSMW_0PmRYfW-dduHTZo,557886
265
+ phoenix/server/static/assets/vendor-CQYk2bLC.js,sha256=phmdcDjuBvBjCYwSZ3KGj4OSxxvxNsUUZ45mBPZngEI,1435307
266
266
  phoenix/server/static/assets/vendor-DxkFTwjz.css,sha256=nZrkr0u6NNElFGvpWHk9GTHeGoibCXCli1bE7mXZGZg,1816
267
- phoenix/server/static/assets/vendor-arizeai-BU1VHwXB.js,sha256=6rYhFTNVr64dh6y8iVOiRUr9YGLxTXJO2vbOlvltamE,304401
268
- phoenix/server/static/assets/vendor-codemirror-BDMHmh1x.js,sha256=nHzc7sIu8XC6Tc0yGtmbxFpNjid2lVW7kuJ19l7QNRE,516470
269
- phoenix/server/static/assets/vendor-recharts-BATX_8yP.js,sha256=lm_k7iQ4lulnBnESotJGLmQO_WfulqzciqGCrkQ6lww,282859
267
+ phoenix/server/static/assets/vendor-arizeai-DgvoPlCK.js,sha256=YZon_DqnY1fuUu3pFamINewm0-yP6_KB3wRcb9b-XkE,304401
268
+ phoenix/server/static/assets/vendor-codemirror-DcWFlULW.js,sha256=JTd-0Dlowm520AVf7lImq_lhDoBlVjcAK9Vy4K8mSVs,516470
269
+ phoenix/server/static/assets/vendor-recharts-BaQGdoah.js,sha256=yCS2cZ7HRKLxB9yx-WZyhBtGmtbcJ-AAhoww-p7lAt4,282859
270
270
  phoenix/server/static/assets/vendor-three-DwGkEfCM.js,sha256=0D12ZgKzfKCTSdSTKJBFR2RZO_xxeMXrqDp0AszZqHY,620972
271
271
  phoenix/server/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
272
272
  phoenix/server/templates/index.html,sha256=ULNlp0-agU8pH4wCIapE1goqnwkbctAoQRgrfwH_irg,4379
@@ -291,7 +291,7 @@ phoenix/trace/trace_dataset.py,sha256=jKXvta-rZuYMwDTytoJtJpSuV-3Hci6vWq31_rffHd
291
291
  phoenix/trace/utils.py,sha256=lWinMM7Tsq_DCsBD5Ck97lxouBHrY4muGNsh8JD3qg4,1694
292
292
  phoenix/trace/dsl/README.md,sha256=ihmP9zGUC5V-TDbzKla76LuyDqPDQIBUH2BORwxNI68,2902
293
293
  phoenix/trace/dsl/__init__.py,sha256=WIQIjJg362XD3s50OsPJJ0xbDsGp41bSv7vDllLrPuA,144
294
- phoenix/trace/dsl/filter.py,sha256=9NwATCUOgJ4Pms8XsEcinROUuxZ9UW-ISV09o65Ms70,32600
294
+ phoenix/trace/dsl/filter.py,sha256=FKa8sIGKoTGMw-iloK87q-lQt7WcVlevWE6WS_tBFWI,30619
295
295
  phoenix/trace/dsl/helpers.py,sha256=STQtbmF3yI97GM4yH_V--mrGe1JqldUJJc5LO1o4NWo,3919
296
296
  phoenix/trace/dsl/query.py,sha256=Mjk2ntKUmRZCCscpt0dMrzo26NhhwtdhC_s9itR3Ycc,30404
297
297
  phoenix/trace/v1/__init__.py,sha256=-IbAD0ruESMjvQLvGAg9CTfjBUATFDx1OXseDPis6-0,88
@@ -306,8 +306,8 @@ phoenix/utilities/logging.py,sha256=B8t2WPULOwVyuGLRLbwKsw5N41N26vtgF-lCAYgWTEk,
306
306
  phoenix/utilities/project.py,sha256=8IJuMM4yUMoooPi37sictGj8Etu9rGmq6RFtc9848cQ,436
307
307
  phoenix/utilities/re.py,sha256=nr_B0txj_7CXc45953X6vr2KCRSWMuaXJSEkL8s8Sjc,2036
308
308
  phoenix/utilities/span_store.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
309
- arize_phoenix-5.1.4.dist-info/METADATA,sha256=dJXHwHorZ7a3TOTwg12O0Thp4TSnbar7HrUF9QB_VoY,11833
310
- arize_phoenix-5.1.4.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
311
- arize_phoenix-5.1.4.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
312
- arize_phoenix-5.1.4.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
313
- arize_phoenix-5.1.4.dist-info/RECORD,,
309
+ arize_phoenix-5.1.6.dist-info/METADATA,sha256=1rGHnsEZnVX5YeAnzItvZpm-JS6nqrA8-EWTr-9kDt0,11631
310
+ arize_phoenix-5.1.6.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
311
+ arize_phoenix-5.1.6.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
312
+ arize_phoenix-5.1.6.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
313
+ arize_phoenix-5.1.6.dist-info/RECORD,,
@@ -17,7 +17,7 @@ class Hdbscan:
17
17
  cluster_selection_epsilon: float = 0.0
18
18
 
19
19
  def find_clusters(self, mat: Matrix) -> List[RawCluster]:
20
- from hdbscan import HDBSCAN
20
+ from fast_hdbscan import HDBSCAN
21
21
 
22
22
  cluster_ids: npt.NDArray[np.int_] = HDBSCAN(**asdict(self)).fit_predict(mat)
23
23
  ans: List[RawCluster] = [set() for _ in range(np.max(cluster_ids) + 1)]
phoenix/server/app.py CHANGED
@@ -22,6 +22,7 @@ from typing import (
22
22
  Optional,
23
23
  Sequence,
24
24
  Tuple,
25
+ Type,
25
26
  TypedDict,
26
27
  Union,
27
28
  cast,
@@ -43,6 +44,7 @@ from starlette.responses import PlainTextResponse, Response
43
44
  from starlette.staticfiles import StaticFiles
44
45
  from starlette.templating import Jinja2Templates
45
46
  from starlette.types import Scope, StatefulLifespan
47
+ from strawberry.extensions import SchemaExtension
46
48
  from strawberry.fastapi import GraphQLRouter
47
49
  from strawberry.schema import BaseSchema
48
50
  from typing_extensions import TypeAlias
@@ -672,7 +674,8 @@ def create_app(
672
674
  initial_batch_of_evaluations=initial_batch_of_evaluations,
673
675
  )
674
676
  tracer_provider = None
675
- strawberry_extensions = schema.get_extensions()
677
+ strawberry_extensions: List[Union[Type[SchemaExtension], SchemaExtension]] = []
678
+ strawberry_extensions.extend(schema.get_extensions())
676
679
  if server_instrumentation_is_enabled():
677
680
  tracer_provider = initialize_opentelemetry_tracer_provider()
678
681
  from opentelemetry.trace import TracerProvider
@@ -1,32 +1,32 @@
1
1
  {
2
- "_components-rP68rA45.js": {
3
- "file": "assets/components-rP68rA45.js",
2
+ "_components-4ANbS7sG.js": {
3
+ "file": "assets/components-4ANbS7sG.js",
4
4
  "name": "components",
5
5
  "imports": [
6
- "_vendor-D8cj1ZYg.js",
7
- "_vendor-arizeai-BU1VHwXB.js",
8
- "_pages-gwtz6mex.js",
6
+ "_vendor-CQYk2bLC.js",
7
+ "_vendor-arizeai-DgvoPlCK.js",
8
+ "_pages-IkQNKgib.js",
9
9
  "_vendor-three-DwGkEfCM.js",
10
- "_vendor-codemirror-BDMHmh1x.js"
10
+ "_vendor-codemirror-DcWFlULW.js"
11
11
  ]
12
12
  },
13
- "_pages-gwtz6mex.js": {
14
- "file": "assets/pages-gwtz6mex.js",
13
+ "_pages-IkQNKgib.js": {
14
+ "file": "assets/pages-IkQNKgib.js",
15
15
  "name": "pages",
16
16
  "imports": [
17
- "_vendor-D8cj1ZYg.js",
18
- "_vendor-arizeai-BU1VHwXB.js",
19
- "_components-rP68rA45.js",
20
- "_vendor-recharts-BATX_8yP.js",
21
- "_vendor-codemirror-BDMHmh1x.js"
17
+ "_vendor-CQYk2bLC.js",
18
+ "_vendor-arizeai-DgvoPlCK.js",
19
+ "_components-4ANbS7sG.js",
20
+ "_vendor-recharts-BaQGdoah.js",
21
+ "_vendor-codemirror-DcWFlULW.js"
22
22
  ]
23
23
  },
24
24
  "_vendor-!~{003}~.js": {
25
25
  "file": "assets/vendor-DxkFTwjz.css",
26
26
  "src": "_vendor-!~{003}~.js"
27
27
  },
28
- "_vendor-D8cj1ZYg.js": {
29
- "file": "assets/vendor-D8cj1ZYg.js",
28
+ "_vendor-CQYk2bLC.js": {
29
+ "file": "assets/vendor-CQYk2bLC.js",
30
30
  "name": "vendor",
31
31
  "imports": [
32
32
  "_vendor-three-DwGkEfCM.js"
@@ -35,25 +35,25 @@
35
35
  "assets/vendor-DxkFTwjz.css"
36
36
  ]
37
37
  },
38
- "_vendor-arizeai-BU1VHwXB.js": {
39
- "file": "assets/vendor-arizeai-BU1VHwXB.js",
38
+ "_vendor-arizeai-DgvoPlCK.js": {
39
+ "file": "assets/vendor-arizeai-DgvoPlCK.js",
40
40
  "name": "vendor-arizeai",
41
41
  "imports": [
42
- "_vendor-D8cj1ZYg.js"
42
+ "_vendor-CQYk2bLC.js"
43
43
  ]
44
44
  },
45
- "_vendor-codemirror-BDMHmh1x.js": {
46
- "file": "assets/vendor-codemirror-BDMHmh1x.js",
45
+ "_vendor-codemirror-DcWFlULW.js": {
46
+ "file": "assets/vendor-codemirror-DcWFlULW.js",
47
47
  "name": "vendor-codemirror",
48
48
  "imports": [
49
- "_vendor-D8cj1ZYg.js"
49
+ "_vendor-CQYk2bLC.js"
50
50
  ]
51
51
  },
52
- "_vendor-recharts-BATX_8yP.js": {
53
- "file": "assets/vendor-recharts-BATX_8yP.js",
52
+ "_vendor-recharts-BaQGdoah.js": {
53
+ "file": "assets/vendor-recharts-BaQGdoah.js",
54
54
  "name": "vendor-recharts",
55
55
  "imports": [
56
- "_vendor-D8cj1ZYg.js"
56
+ "_vendor-CQYk2bLC.js"
57
57
  ]
58
58
  },
59
59
  "_vendor-three-DwGkEfCM.js": {
@@ -61,18 +61,18 @@
61
61
  "name": "vendor-three"
62
62
  },
63
63
  "index.tsx": {
64
- "file": "assets/index-CHLTxqHu.js",
64
+ "file": "assets/index-CwRlD2_T.js",
65
65
  "name": "index",
66
66
  "src": "index.tsx",
67
67
  "isEntry": true,
68
68
  "imports": [
69
- "_vendor-D8cj1ZYg.js",
70
- "_vendor-arizeai-BU1VHwXB.js",
71
- "_pages-gwtz6mex.js",
72
- "_components-rP68rA45.js",
69
+ "_vendor-CQYk2bLC.js",
70
+ "_vendor-arizeai-DgvoPlCK.js",
71
+ "_pages-IkQNKgib.js",
72
+ "_components-4ANbS7sG.js",
73
73
  "_vendor-three-DwGkEfCM.js",
74
- "_vendor-recharts-BATX_8yP.js",
75
- "_vendor-codemirror-BDMHmh1x.js"
74
+ "_vendor-recharts-BaQGdoah.js",
75
+ "_vendor-codemirror-DcWFlULW.js"
76
76
  ]
77
77
  }
78
78
  }