cu-cli 0.1.0b1__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.
Files changed (56) hide show
  1. cu_cli/__init__.py +17 -0
  2. cu_cli/__main__.py +11 -0
  3. cu_cli/apiversion.py +124 -0
  4. cu_cli/cli.py +138 -0
  5. cu_cli/client.py +138 -0
  6. cu_cli/commands/__init__.py +4 -0
  7. cu_cli/commands/_command_spec.py +94 -0
  8. cu_cli/commands/_help.py +33 -0
  9. cu_cli/commands/_infra_models.py +184 -0
  10. cu_cli/commands/_infra_wizard.py +630 -0
  11. cu_cli/commands/_model_setup.py +46 -0
  12. cu_cli/commands/_options.py +112 -0
  13. cu_cli/commands/analyze.py +631 -0
  14. cu_cli/commands/analyzer.py +1462 -0
  15. cu_cli/commands/defaults.py +172 -0
  16. cu_cli/commands/doctor.py +166 -0
  17. cu_cli/commands/env_var.py +67 -0
  18. cu_cli/commands/infra.py +302 -0
  19. cu_cli/commands/profile_cmd.py +525 -0
  20. cu_cli/commands/upgrade.py +120 -0
  21. cu_cli/core/__init__.py +17 -0
  22. cu_cli/core/analyze.py +44 -0
  23. cu_cli/core/analyzers.py +30 -0
  24. cu_cli/core/azure_resources.py +486 -0
  25. cu_cli/core/defaults.py +18 -0
  26. cu_cli/core/doctor.py +42 -0
  27. cu_cli/core/foundry.py +68 -0
  28. cu_cli/core/infra_models.py +367 -0
  29. cu_cli/core/inputs.py +209 -0
  30. cu_cli/core/schema.py +24 -0
  31. cu_cli/errors.py +174 -0
  32. cu_cli/exit_codes.py +20 -0
  33. cu_cli/modality.py +24 -0
  34. cu_cli/output.py +179 -0
  35. cu_cli/profile.py +30 -0
  36. cu_cli/py.typed +0 -0
  37. cu_cli/resources/__init__.py +4 -0
  38. cu_cli/resources/azd_template/README.md +187 -0
  39. cu_cli/resources/azd_template/azure.yaml +27 -0
  40. cu_cli/resources/azd_template/hooks/postprovision.ps1 +320 -0
  41. cu_cli/resources/azd_template/hooks/postprovision.sh +299 -0
  42. cu_cli/resources/azd_template/infra/main.bicep +115 -0
  43. cu_cli/resources/azd_template/infra/main.parameters.json +30 -0
  44. cu_cli/resources/azd_template/infra/models.json +1 -0
  45. cu_cli/resources/azd_template/infra/modules/foundry.bicep +122 -0
  46. cu_cli/schema_validate.py +28 -0
  47. cu_cli/spec_validate.py +18 -0
  48. cu_cli/telemetry.py +42 -0
  49. cu_cli/update_check.py +154 -0
  50. cu_cli/update_provider.py +92 -0
  51. cu_cli/windows_self_upgrade.py +245 -0
  52. cu_cli-0.1.0b1.dist-info/METADATA +345 -0
  53. cu_cli-0.1.0b1.dist-info/RECORD +56 -0
  54. cu_cli-0.1.0b1.dist-info/WHEEL +5 -0
  55. cu_cli-0.1.0b1.dist-info/entry_points.txt +3 -0
  56. cu_cli-0.1.0b1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,245 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT license.
3
+
4
+ """Windows-only detached self-upgrade helper.
5
+
6
+ On Windows, a running ``cu.exe`` holds an exclusive file lock on its own
7
+ executable image. ``pip install --upgrade`` is non-atomic (uninstall, then
8
+ install); if the install step cannot replace the locked ``cu.exe``, the
9
+ uninstall has already completed and the environment is left with no
10
+ importable ``cu_cli`` module at all.
11
+
12
+ POSIX allows unlinking/replacing a file that is currently executing, so this
13
+ failure mode is Windows-specific — the fix below is only exercised there.
14
+
15
+ The fix: don't run pip synchronously from inside ``cu.exe``. Instead, write a
16
+ small, dependency-free helper script to disk and launch it as a fully
17
+ detached process, then let ``cu.exe`` return control to the shell (and exit)
18
+ immediately. The helper:
19
+
20
+ 1. waits for the original ``cu.exe`` process to actually exit, releasing the
21
+ file lock;
22
+ 2. runs ``pip install --upgrade`` for the target version, retrying a few
23
+ times in case another handle (AV scanning, indexing) still holds the file
24
+ briefly;
25
+ 3. rolls back to the previously installed, known-good ``cu-cli`` (and
26
+ ``cu-cli-core``) version if the upgrade fails, so the environment is never
27
+ left without an importable CLI;
28
+ 4. logs progress/outcome to a log file for later inspection.
29
+
30
+ The helper script intentionally does not import ``cu_cli`` (or any of its
31
+ dependencies) — it must keep working even while the ``cu-cli`` package itself
32
+ is mid-uninstall/reinstall.
33
+ """
34
+
35
+ from __future__ import annotations
36
+
37
+ import json
38
+ import os
39
+ import subprocess
40
+ import sys
41
+ import tempfile
42
+ import textwrap
43
+ import uuid
44
+ from pathlib import Path
45
+ from typing import Callable, Mapping, Sequence
46
+
47
+ _LOG_DIR = Path.home() / ".cu"
48
+
49
+
50
+ def is_windows() -> bool:
51
+ """Return whether the current platform needs the detached-helper path."""
52
+ return sys.platform.startswith("win")
53
+
54
+
55
+ def default_log_path() -> Path:
56
+ return _LOG_DIR / "upgrade.log"
57
+
58
+
59
+ def _rollback_args(python_exe: str, current_version: str, core_version: str | None) -> list[str]:
60
+ args = [
61
+ python_exe,
62
+ "-m",
63
+ "pip",
64
+ "install",
65
+ "--force-reinstall",
66
+ f"cu-cli=={current_version}",
67
+ ]
68
+ if core_version:
69
+ args.append(f"cu-cli-core=={core_version}")
70
+ return args
71
+
72
+
73
+ _HELPER_SOURCE = textwrap.dedent(
74
+ '''\
75
+ """Detached helper for `cu upgrade` on Windows (auto-generated, no cu_cli import).
76
+
77
+ Do not edit: regenerated on every `cu upgrade`. Safe to delete once the
78
+ logged outcome shows "upgrade succeeded" or "rollback".
79
+ """
80
+ import json
81
+ import os
82
+ import subprocess
83
+ import sys
84
+ import time
85
+
86
+ with open(__file__.rsplit(".", 1)[0] + ".json", "r", encoding="utf-8") as _f:
87
+ _CONFIG = json.load(_f)
88
+
89
+ PARENT_PID = _CONFIG["parent_pid"]
90
+ UPGRADE_ARGS = _CONFIG["upgrade_args"]
91
+ ROLLBACK_ARGS = _CONFIG["rollback_args"]
92
+ ENV_OVERRIDES = _CONFIG["env_overrides"]
93
+ LOG_PATH = _CONFIG["log_path"]
94
+ WAIT_TIMEOUT_SECONDS = _CONFIG["wait_timeout_seconds"]
95
+ RETRY_ATTEMPTS = _CONFIG["retry_attempts"]
96
+ RETRY_DELAY_SECONDS = _CONFIG["retry_delay_seconds"]
97
+
98
+
99
+ def _log(message):
100
+ try:
101
+ with open(LOG_PATH, "a", encoding="utf-8") as handle:
102
+ handle.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} {message}\\n")
103
+ except OSError:
104
+ pass
105
+
106
+
107
+ def _wait_for_parent_exit(pid, timeout_seconds):
108
+ try:
109
+ import ctypes
110
+
111
+ synchronize = 0x00100000
112
+ query_limited = 0x1000
113
+ handle = ctypes.windll.kernel32.OpenProcess(
114
+ synchronize | query_limited, False, pid
115
+ )
116
+ if not handle:
117
+ return # already exited, or we can't see it: proceed anyway
118
+ try:
119
+ ctypes.windll.kernel32.WaitForSingleObject(
120
+ handle, int(timeout_seconds * 1000)
121
+ )
122
+ finally:
123
+ ctypes.windll.kernel32.CloseHandle(handle)
124
+ except Exception:
125
+ # Best effort only: if the wait itself fails, fall through and
126
+ # rely on the pip retry loop below.
127
+ time.sleep(2)
128
+
129
+
130
+ def _run_pip(args, attempts, delay_seconds):
131
+ env = {**os.environ, **ENV_OVERRIDES}
132
+ result = None
133
+ for attempt in range(attempts):
134
+ result = subprocess.run(args, env=env)
135
+ if result.returncode == 0:
136
+ return True
137
+ _log(f"attempt {attempt + 1}/{attempts} failed (exit {result.returncode})")
138
+ time.sleep(delay_seconds)
139
+ return False
140
+
141
+
142
+ def main():
143
+ _log(f"waiting for parent pid {PARENT_PID} to exit")
144
+ _wait_for_parent_exit(PARENT_PID, WAIT_TIMEOUT_SECONDS)
145
+ _log(f"running: {' '.join(UPGRADE_ARGS)}")
146
+ if _run_pip(UPGRADE_ARGS, RETRY_ATTEMPTS, RETRY_DELAY_SECONDS):
147
+ _log("upgrade succeeded")
148
+ return
149
+ _log("upgrade failed; rolling back to previous version")
150
+ if _run_pip(ROLLBACK_ARGS, RETRY_ATTEMPTS, RETRY_DELAY_SECONDS):
151
+ _log("rollback succeeded; previous cu-cli remains usable")
152
+ else:
153
+ _log(
154
+ "rollback FAILED - manual recovery required: "
155
+ + " ".join(ROLLBACK_ARGS)
156
+ )
157
+
158
+
159
+ if __name__ == "__main__":
160
+ main()
161
+ '''
162
+ )
163
+
164
+
165
+ def write_helper_files(
166
+ *,
167
+ parent_pid: int,
168
+ upgrade_args: Sequence[str],
169
+ rollback_args: Sequence[str],
170
+ env_overrides: Mapping[str, str],
171
+ log_path: Path,
172
+ wait_timeout_seconds: float = 30.0,
173
+ retry_attempts: int = 5,
174
+ retry_delay_seconds: float = 2.0,
175
+ ) -> Path:
176
+ """Write the helper script + its config to a temp dir; return the script path."""
177
+ run_dir = Path(tempfile.gettempdir()) / f"cu-upgrade-{uuid.uuid4().hex}"
178
+ run_dir.mkdir(parents=True, exist_ok=True)
179
+ script_path = run_dir / "cu_upgrade_helper.py"
180
+ config_path = run_dir / "cu_upgrade_helper.json"
181
+
182
+ config = {
183
+ "parent_pid": parent_pid,
184
+ "upgrade_args": list(upgrade_args),
185
+ "rollback_args": list(rollback_args),
186
+ "env_overrides": dict(env_overrides),
187
+ "log_path": str(log_path),
188
+ "wait_timeout_seconds": wait_timeout_seconds,
189
+ "retry_attempts": retry_attempts,
190
+ "retry_delay_seconds": retry_delay_seconds,
191
+ }
192
+ config_path.write_text(json.dumps(config), encoding="utf-8")
193
+ script_path.write_text(_HELPER_SOURCE, encoding="utf-8")
194
+ return script_path
195
+
196
+
197
+ def launch_detached(python_exe: str, script_path: Path) -> subprocess.Popen:
198
+ """Launch the helper fully detached so it outlives the current process."""
199
+ creationflags = getattr(subprocess, "DETACHED_PROCESS", 0) | getattr(
200
+ subprocess, "CREATE_NEW_PROCESS_GROUP", 0
201
+ )
202
+ return subprocess.Popen(
203
+ [python_exe, str(script_path)],
204
+ creationflags=creationflags,
205
+ close_fds=True,
206
+ stdin=subprocess.DEVNULL,
207
+ stdout=subprocess.DEVNULL,
208
+ stderr=subprocess.DEVNULL,
209
+ )
210
+
211
+
212
+ def run_windows_upgrade(
213
+ *,
214
+ current_version: str,
215
+ core_version: str | None,
216
+ pip_args: Sequence[str],
217
+ pip_env: Mapping[str, str],
218
+ python_exe: str | None = None,
219
+ parent_pid: int | None = None,
220
+ write_helper: Callable[..., Path] = write_helper_files,
221
+ launch: Callable[[str, Path], subprocess.Popen] = launch_detached,
222
+ log_path: Path | None = None,
223
+ ) -> tuple[int, Path]:
224
+ """Start the detached Windows upgrade helper. Returns (exit_code, log_path).
225
+
226
+ ``cu upgrade`` cannot synchronously guarantee the final outcome, because
227
+ that would require pip to replace the file backing the process still
228
+ running it. Spawning succeeds, so this returns exit code 0; the actual
229
+ upgrade/rollback result is written to ``log_path``.
230
+ """
231
+ python_exe = python_exe or sys.executable
232
+ parent_pid = parent_pid if parent_pid is not None else os.getpid()
233
+ resolved_log_path = log_path or default_log_path()
234
+ resolved_log_path.parent.mkdir(parents=True, exist_ok=True)
235
+
236
+ rollback_args = _rollback_args(python_exe, current_version, core_version)
237
+ script_path = write_helper(
238
+ parent_pid=parent_pid,
239
+ upgrade_args=list(pip_args),
240
+ rollback_args=rollback_args,
241
+ env_overrides=pip_env,
242
+ log_path=resolved_log_path,
243
+ )
244
+ launch(python_exe, script_path)
245
+ return 0, resolved_log_path
@@ -0,0 +1,345 @@
1
+ Metadata-Version: 2.4
2
+ Name: cu-cli
3
+ Version: 0.1.0b1
4
+ Summary: Author, validate, and run Azure Content Understanding custom analyzers from the terminal — advanced document layout, industry-leading OCR, and grounded field extraction with confidence, all backed by Azure Content Understanding.
5
+ Author: Microsoft Corporation
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/Azure/content-understanding-toolkit/tree/main/cu-cli
8
+ Project-URL: Repository, https://github.com/Azure/content-understanding-toolkit
9
+ Project-URL: Issues, https://github.com/Azure/content-understanding-toolkit/issues
10
+ Project-URL: Documentation, https://aka.ms/cu-doc
11
+ Keywords: azure,content-understanding,document-intelligence,ocr,pdf,extract,field-extraction,analyzer,cli,markdown
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Classifier: Topic :: Text Processing
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ Requires-Dist: cu-cli-core<0.2.0,>=0.1.0b1
25
+ Requires-Dist: azure-ai-contentunderstanding>=1.2.0b3
26
+ Requires-Dist: azure-identity>=1.19
27
+ Requires-Dist: azure-mgmt-cognitiveservices>=13.5
28
+ Requires-Dist: click>=8.1
29
+ Requires-Dist: packaging>=23.2
30
+ Requires-Dist: requests>=2.31
31
+ Requires-Dist: rich>=13.7
32
+ Requires-Dist: rich-click>=1.7
33
+ Provides-Extra: dev
34
+ Requires-Dist: pytest>=7.4; extra == "dev"
35
+ Requires-Dist: pytest-cov>=4.1; extra == "dev"
36
+ Requires-Dist: mypy<2,>=1.8; extra == "dev"
37
+ Requires-Dist: ruff<0.16,>=0.5; extra == "dev"
38
+ Requires-Dist: tomli>=2.0; python_version < "3.11" and extra == "dev"
39
+ Requires-Dist: vcrpy>=6.0; extra == "dev"
40
+
41
+ # CU CLI
42
+
43
+ `cu` is the preview command-line interface for Azure Content Understanding in
44
+ Foundry Tools. Use it to provision the required Microsoft Foundry resource,
45
+ optionally deploy selected supported large language models (LLMs) and embeddings
46
+ models, configure Content Understanding defaults, analyze local files, manage
47
+ analyzers, and manage local configuration.
48
+
49
+ > [!IMPORTANT]
50
+ > CU CLI is in preview. Commands and package contracts may change before general
51
+ > availability.
52
+
53
+ ## Content Understanding concepts
54
+
55
+ Content Understanding processes unstructured content, including documents,
56
+ images, audio, and video, into structured output for automation, analytics, and
57
+ search workflows. It is a Foundry Tool that you access through a Microsoft
58
+ Foundry resource in Azure.
59
+
60
+ The Content Understanding documentation uses these terms:
61
+
62
+ - A **file** is the input. It can be a document, image, audio file, video, or
63
+ other [supported file type](https://learn.microsoft.com/azure/ai-services/content-understanding/service-limits#input-file-limits).
64
+ - An **analyzer** defines how Content Understanding processes a file and
65
+ extracts content and structured fields.
66
+ - An **analyzer result** is the output from processing a file. It can include
67
+ extracted Markdown content, structured fields, and modality-specific details.
68
+ - A **prebuilt analyzer** is a ready-to-use analyzer supplied by Content
69
+ Understanding for common content extraction, search, and domain scenarios.
70
+ - A **custom analyzer** is an analyzer you define for your scenario. It uses a
71
+ base analyzer for a content type and a field schema that describes the
72
+ structured fields to extract.
73
+
74
+ CU CLI lets you configure a Microsoft Foundry resource, select an analyzer,
75
+ submit local files, and save analyzer results without calling the REST API
76
+ directly.
77
+
78
+ Further reading:
79
+
80
+ - [What is Content Understanding?](https://learn.microsoft.com/azure/ai-services/content-understanding/overview)
81
+ - [Content Understanding terminology](https://learn.microsoft.com/azure/ai-services/content-understanding/glossary)
82
+
83
+ ## Install
84
+
85
+ Requirements:
86
+
87
+ - Python 3.10 or later
88
+ - [Azure CLI](https://aka.ms/azcli) for login and resource discovery
89
+ - [Azure Developer CLI](https://aka.ms/azd) only when using `cu infra generate`
90
+
91
+ ```bash
92
+ python -m pip install cu-cli
93
+ cu --version
94
+ cu --help
95
+ ```
96
+
97
+ macOS includes an unrelated system command named `cu`. Use the equivalent
98
+ `cu-cli` executable on macOS:
99
+
100
+ ```bash
101
+ cu-cli --help
102
+ ```
103
+
104
+ ## Connect to Microsoft Foundry and check setup
105
+
106
+ You need a Microsoft Foundry resource endpoint. LLM-based prebuilt analyzers and
107
+ custom analyzers also need supported LLM and embeddings deployments plus Content
108
+ Understanding defaults. If any of these are missing, follow the complete
109
+ [Microsoft Foundry provisioning guide](https://github.com/Azure/content-understanding-toolkit/blob/main/cu-cli/docs/provisioning.md).
110
+
111
+ A CU CLI profile is local configuration for one Microsoft Foundry resource. It
112
+ stores the endpoint, authentication method, API version, and optional model
113
+ deployment mappings; it is not an Azure resource. For a ready resource,
114
+ configure the automatically available `default` profile. With Microsoft Entra
115
+ ID authentication:
116
+
117
+ ```bash
118
+ cu profile set endpoint https://<resource-name>.services.ai.azure.com/
119
+ cu profile set auth_mode login
120
+ az login
121
+ cu doctor
122
+ ```
123
+
124
+ Alternatively, use a resource key:
125
+
126
+ ```bash
127
+ cu profile set endpoint https://<resource-name>.services.ai.azure.com/
128
+ cu profile set api_key <key>
129
+ cu doctor
130
+ ```
131
+
132
+ The API key is redacted by `cu profile get` and `cu profile show`. `cu doctor`
133
+ checks the API version, endpoint, authentication, service connectivity, and
134
+ Content Understanding defaults. It exits nonzero when a required check fails,
135
+ so it can serve as a readiness gate.
136
+
137
+ ## Supported Content Understanding API versions
138
+
139
+ Content Understanding API version. Known versions: 2025-11-01 (GA) and
140
+ 2026-06-01-preview (preview); any YYYY-MM-DD-preview version is also accepted.
141
+
142
+ CU CLI defaults to `2025-11-01`. Override the version with `cu profile set
143
+ api_version <version>`, the `--api-version` flag, or the `CU_API_VERSION`
144
+ environment variable; run `cu profile show` to see the active profile's
145
+ configured version.
146
+
147
+ The preview API adds capabilities beyond the GA version. CU CLI returns
148
+ result-based capabilities, such as document metadata and signatures, through
149
+ the normal analysis result without dedicated CLI options. Inline analysis is
150
+ the only preview capability that requires a new CU CLI option:
151
+ `cu analyze --inline` runs supported analysis synchronously and returns the
152
+ result directly instead of using the default long-running-operation (LRO)
153
+ polling flow.
154
+
155
+ ```bash
156
+ cu analyze --inline --api-version 2026-06-01-preview document.pdf --analyzer prebuilt-layout
157
+ ```
158
+
159
+ Save the preview version to a profile to avoid passing `--api-version` on every
160
+ call: `cu profile set api_version 2026-06-01-preview`. Pin to `2025-11-01` for
161
+ production workloads that don't need preview capabilities.
162
+
163
+ Further reading:
164
+
165
+ - [What's new in the `2026-06-01-preview` API](https://learn.microsoft.com/azure/ai-services/content-understanding/whats-new#july-2026)
166
+ - Run `cu analyze --help` for all analyze options.
167
+
168
+ ## Use prebuilt analyzers
169
+
170
+ List the prebuilt analyzers available to the configured resource:
171
+
172
+ ```bash
173
+ cu analyzer list
174
+ ```
175
+
176
+ Start with the `prebuilt-layout` content extraction analyzer. It extracts text,
177
+ paragraphs, tables, figures, and document structure without requiring a language
178
+ model or embeddings model. `-a` is the short form of `--analyzer`:
179
+
180
+ ```bash
181
+ # Generate Markdown from the analyzer result with the CU SDK's to_llm_input().
182
+ cu analyze ./document.pdf -a prebuilt-layout
183
+ ```
184
+
185
+ Markdown generated by the Content Understanding SDK's `to_llm_input()` helper is
186
+ the default output format. The helper formats field extraction results as
187
+ Markdown with YAML frontmatter so they can be used as generative AI model input.
188
+ Use `--llm-input` to select this default view explicitly, or use `--json` to
189
+ return the complete analyzer result as JSON. See the
190
+ [Content Understanding SDK `to_llm_input()` helper](https://learn.microsoft.com/azure/ai-services/content-understanding/whats-new#april-2026).
191
+
192
+ Domain-specific prebuilt analyzers, such as `prebuilt-invoice`, extract a
193
+ defined set of structured fields. They require the model setup described in
194
+ [Deploy models and configure defaults](https://github.com/Azure/content-understanding-toolkit/blob/main/cu-cli/docs/provisioning.md#deploy-models-and-configure-defaults):
195
+
196
+ ```bash
197
+ cu analyze ./invoice.pdf --analyzer prebuilt-invoice --json
198
+ ```
199
+
200
+ The command returns an analyzer result. Use `--json` when you want the
201
+ structured result as JSON.
202
+
203
+ Analyze several files into one output directory. `--pattern` requires
204
+ `--source`, because a positional path can be either a file or a directory and
205
+ `--pattern` only makes sense once a directory is named explicitly:
206
+
207
+ ```bash
208
+ cu analyze --source ./documents --pattern "*.pdf" --output-dir ./results
209
+ ```
210
+
211
+ Each result is written under `./results` and keeps the input path relative to
212
+ `./documents`. For example, `./documents/invoice-01.pdf` produces
213
+ `./results/invoice-01.pdf.result.md`. Markdown results use the
214
+ `.result.md` suffix; adding `--json` produces `.result.json` files instead.
215
+
216
+ Further reading:
217
+
218
+ - [Prebuilt analyzers](https://learn.microsoft.com/azure/ai-services/content-understanding/concepts/prebuilt-analyzers)
219
+ - [Supported input files and service limits](https://learn.microsoft.com/azure/ai-services/content-understanding/service-limits#input-file-limits)
220
+ - Run `cu analyze --help` for input, output, overwrite, concurrency, and reporting options.
221
+
222
+ ## Create a custom analyzer
223
+
224
+ A custom analyzer lets you define the structured fields needed by your
225
+ application. Its analyzer schema identifies a base analyzer for the content type
226
+ and includes a field schema that describes the field names, value types, and
227
+ generation methods.
228
+
229
+ Custom analyzers require supported model deployments and configured Content
230
+ Understanding defaults. Confirm the model-to-deployment mappings before creating
231
+ the analyzer:
232
+
233
+ ```bash
234
+ # Show the Content Understanding defaults configured on the resource.
235
+ cu defaults show
236
+ ```
237
+
238
+ If the required mappings are missing, follow
239
+ [Configure defaults manually](https://github.com/Azure/content-understanding-toolkit/blob/main/cu-cli/docs/provisioning.md#configure-defaults-manually)
240
+ to configure them. Then generate a starter analyzer schema from a representative
241
+ file:
242
+
243
+ ```bash
244
+ # Generate a schema from a representative document.
245
+ cu analyzer schema create \
246
+ --from-sample ./invoice.pdf \
247
+ --output-file ./invoice-schema.json
248
+
249
+ # Review and update the generated schema for your extraction requirements,
250
+ # then create the analyzer.
251
+ cu analyzer create --name invoice_v1 --schema ./invoice-schema.json
252
+
253
+ # Run the analyzer against the sample and summarize whether fields were returned
254
+ # and any confidence values supplied by the service. This is not an accuracy
255
+ # benchmark and does not compare the result with labeled ground truth.
256
+ cu analyzer test invoice_v1 ./invoice.pdf
257
+
258
+ cu analyze ./invoice.pdf --analyzer invoice_v1 --json
259
+ ```
260
+
261
+ Schema generation preserves existing files by default. Pass `--force` only when
262
+ you intentionally want to replace the selected `--output-file`.
263
+
264
+ Further reading:
265
+
266
+ - [Create a custom analyzer](https://learn.microsoft.com/azure/ai-services/content-understanding/tutorial/create-custom-analyzer)
267
+ - [Supported generative models](https://learn.microsoft.com/azure/ai-services/content-understanding/service-limits#supported-generative-models)
268
+ - Run `cu analyzer --help` for analyzer management and testing commands.
269
+
270
+ ## Command overview
271
+
272
+ | Command | Purpose |
273
+ | --- | --- |
274
+ | `cu analyze` | Analyze local files and return analyzer results. |
275
+ | `cu analyzer` | List, show, create, copy, delete, and test analyzers; create and validate local analyzer schemas. |
276
+ | `cu defaults` | Read or configure Content Understanding defaults that map models to deployments. |
277
+ | `cu profile` | Manage local CU CLI endpoint, authentication, API, and model settings. |
278
+ | `cu infra generate` | Generate an azd/Bicep project used to provision a Microsoft Foundry resource and configure Content Understanding. Run `azd up` to provision it. |
279
+ | `cu doctor` | Verify the active CU CLI profile, authentication, and model readiness. |
280
+ | `cu env-var` | Inspect supported environment-variable overrides. |
281
+
282
+ Every command provides examples:
283
+
284
+ ```bash
285
+ cu profile --help
286
+ cu analyzer copy --help
287
+ cu infra generate --help
288
+ ```
289
+
290
+ ## CU CLI usage guide
291
+
292
+ Use this README for installation, resource connection, and the first successful
293
+ analysis. For Azure provisioning, see the
294
+ [Microsoft Foundry provisioning guide](https://github.com/Azure/content-understanding-toolkit/blob/main/cu-cli/docs/provisioning.md). For detailed
295
+ operational guidance, see the
296
+ [CU CLI usage guide](https://github.com/Azure/content-understanding-toolkit/blob/main/cu-cli/docs/usage-guide.md). It explains:
297
+
298
+ - CU CLI profile resolution and environment-variable overrides
299
+ - safe batch previews, output handling, and machine-readable reports
300
+ - analyzer schema, lifecycle, testing, and cross-resource copy workflows
301
+ - Content Understanding defaults and troubleshooting
302
+
303
+ ## More information
304
+
305
+ - [Azure Content Understanding documentation](https://aka.ms/cu-doc)
306
+ - [Support](https://github.com/Azure/content-understanding-toolkit/blob/main/cu-cli/SUPPORT.md)
307
+ - [Contributing](https://github.com/Azure/content-understanding-toolkit/blob/main/cu-cli/CONTRIBUTING.md)
308
+
309
+ The standalone distribution is `cu-cli`. It depends on the separately built
310
+ `cu-cli-core` implementation package in this same product tree. `cu-cli-core`
311
+ is an internal implementation boundary for official CU command-line frontends;
312
+ install and use `cu-cli` rather than importing the core package directly.
313
+
314
+ ## Telemetry
315
+
316
+ CU CLI adds `cu-cli/<version>` to the standard Azure SDK `User-Agent` header on
317
+ requests to the Azure Content Understanding service. Microsoft uses this
318
+ identifier to understand CU CLI adoption. CU CLI does not add customer content
319
+ or separate usage and analytics events to this telemetry.
320
+
321
+ To remove the `cu-cli/<version>` identifier, set `CU_TELEMETRY=off` (also
322
+ accepts `0`, `false`, or `no`) before running CU CLI. The Azure SDK continues to
323
+ send its standard `User-Agent` as part of service requests. See the repository
324
+ [data collection notice](https://github.com/Azure/content-understanding-toolkit#data-collection)
325
+ for more information.
326
+
327
+ ## Use multiple profiles
328
+
329
+ If you work with multiple resources, create named profiles and either activate
330
+ one or select it per command:
331
+
332
+ ```bash
333
+ cu profile create dev
334
+ cu profile set endpoint https://<dev-resource>.services.ai.azure.com/ --name dev
335
+ cu profile create prod
336
+ cu profile set endpoint https://<prod-resource>.services.ai.azure.com/ --name prod
337
+
338
+ cu profile set-active dev
339
+ cu analyzer list
340
+ cu analyzer list --profile prod
341
+ cu doctor --profile prod
342
+ ```
343
+
344
+ See the [CU CLI profile usage guide](https://github.com/Azure/content-understanding-toolkit/blob/main/cu-cli/docs/usage-guide.md#cu-cli-profiles) for
345
+ profile resolution and environment-variable overrides.
@@ -0,0 +1,56 @@
1
+ cu_cli/__init__.py,sha256=fNEG_VsQlqBY7pcBFmxqW11GgSnmfyiReuP76IoqGag,478
2
+ cu_cli/__main__.py,sha256=w_pUFk4iLDoh1Kh5BXRoTuSw4AXHQSgfhmcy_mtILmo,205
3
+ cu_cli/apiversion.py,sha256=khC7v1HioXoXPOBoqAGIS-rRu_WK5VqooKMhUGnehDQ,4088
4
+ cu_cli/cli.py,sha256=rA3GAk0ZpuPFYleHe5WpooCkRuXxyu68IWzCDZ2YDYw,4884
5
+ cu_cli/client.py,sha256=GyfEp2-orgvmw-5pHGc0YrIQQtKouPxiV_CY_kx0YVI,5097
6
+ cu_cli/errors.py,sha256=upmEupCkxgkrYySwuvYn8ltpAz_AZcYKLRc0wX-fLlE,6993
7
+ cu_cli/exit_codes.py,sha256=o2sq68adhmtTk-GGna7G5yDlCdNEeZIagrA_sV4sDcs,506
8
+ cu_cli/modality.py,sha256=nUtuGxX64YIgSCXQ9hVKkL4UjwZMwnK48eGlqrXhKQk,945
9
+ cu_cli/output.py,sha256=CUYvlc7eBrLo72CO52JGJiJNgVezMMDO9_hRN3vcGz8,5935
10
+ cu_cli/profile.py,sha256=QudPVd9fOh_hwo-nZYmupnN0mt4V6FJDBmPrfY828Ug,692
11
+ cu_cli/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ cu_cli/schema_validate.py,sha256=KbRYZAMO00GGULPmhkrqTGcdE8W5zkt4g9LuIGJTnyQ,632
13
+ cu_cli/spec_validate.py,sha256=PdKOKpUMSYj_jXGB85_ZE1W4J4_r-_GFzKPboiprkiY,414
14
+ cu_cli/telemetry.py,sha256=aQ8_T72l2yX-kcxv-LgpxCNdGdePOtHrfGItIBafY-w,1586
15
+ cu_cli/update_check.py,sha256=fH5pw0bvKuJ1x6gEo3adlwuMOimdjKuZabeeN_Mut4k,4806
16
+ cu_cli/update_provider.py,sha256=vQP-AMALk-LnU6HQ08hhVTbyCRYdO1EbbEOd35x2WX4,2952
17
+ cu_cli/windows_self_upgrade.py,sha256=-BmdBe-o4ZZcjuBhq73Jte-0eQboOri1FqVd4tAVcvk,8412
18
+ cu_cli/commands/__init__.py,sha256=B1-toem4whTXdehhZ_s_FjdE1Tjd-2brjluf2Qj4CZc,101
19
+ cu_cli/commands/_command_spec.py,sha256=TdGiGS6wFldTb9fghICf1LKwqGeIfaCKmaGu8KK7-VU,3037
20
+ cu_cli/commands/_help.py,sha256=DFwZj7Qr_7jVN1oqYGk9zgFojinBvYGE0akCaN5SSCE,1191
21
+ cu_cli/commands/_infra_models.py,sha256=MQbKJ-9L63-8lzBvmOSeKUq0FP7lIz6Ah-9P2hOP63M,6266
22
+ cu_cli/commands/_infra_wizard.py,sha256=773yaRfhLeMgvqhOgSkdAyThqK-O_qANAC6twlhnPCU,22724
23
+ cu_cli/commands/_model_setup.py,sha256=wHyDMdEa1UMx7yZPi-GYw1Fk7niinVvlOwjvYg7Yeas,1668
24
+ cu_cli/commands/_options.py,sha256=iOBPk0HK1OexAaHM8VfsvD_XFrIh-ZBV2v5gr4drjsI,3796
25
+ cu_cli/commands/analyze.py,sha256=n1jyhojWwOB2g_e7cpQEWj9yBPkLsEsKRp1Sm9pKBYo,25209
26
+ cu_cli/commands/analyzer.py,sha256=ZGEnGeT0cIPeBPfKzCD5JKy_CHWNsVSGHimLRFb0eB8,56444
27
+ cu_cli/commands/defaults.py,sha256=NDdE3r3Ew60glWC1U51LSwtxNwN_2UhjyPl_NMz4NEE,5521
28
+ cu_cli/commands/doctor.py,sha256=m9epNBjAAqkloqTfL8uQ338XHfed9yePJFDLQTkJXL8,7342
29
+ cu_cli/commands/env_var.py,sha256=jP8k5tbZ5v-L3fwMmOYCY8VSEr4z7jIv2Ne3OoAt7m4,2183
30
+ cu_cli/commands/infra.py,sha256=aFrrnNUTWGvVXv-Lmv1G1J1eCr2QL8App1s8ldPY7b4,10834
31
+ cu_cli/commands/profile_cmd.py,sha256=ucoPeMiHkaSyX2YeVgwFW7erKNcyfCGIsaoY0b-T8-o,17263
32
+ cu_cli/commands/upgrade.py,sha256=Fqc2IGcD0Y_7gesJz-AtUZGX-_PjfmKksX-BjCdC7C8,5125
33
+ cu_cli/core/__init__.py,sha256=wdd_xMCNyN_rBm3hCGcedo-ZJPZ4qOKwQ1Rnlox98g4,784
34
+ cu_cli/core/analyze.py,sha256=NNcgmyKCANamWW0tIBlrRLadPFpYvZAfChy2EFSoy3I,1036
35
+ cu_cli/core/analyzers.py,sha256=Z9vgNCxKwTaYh9aA7DS2UiH0_30Cs3iyaT4mrKcPcck,729
36
+ cu_cli/core/azure_resources.py,sha256=9vFbBtyC66E8Q3RqGqiSGEK4lIxVT9cOfHOIODwPagg,20000
37
+ cu_cli/core/defaults.py,sha256=tPLWda1zDhQauyyjv0xX2j-oGqg3ZPvVB2o0vQ2g-aI,408
38
+ cu_cli/core/doctor.py,sha256=JjIO0jIuEZRA5ePt8TKDQf7AW_f1M3dF7xX8DSoCLX8,1673
39
+ cu_cli/core/foundry.py,sha256=_MZR3YN1vtiLW5Hhx5PwGUCbZR76U6jb6gvBJNgoczU,2574
40
+ cu_cli/core/infra_models.py,sha256=frF-xCetihSkeQjcO2pRARL9VPHTqlRQN1SaNn-yzGM,12994
41
+ cu_cli/core/inputs.py,sha256=sx7mPjabKPpg_ZFDVHvyqwRPsAqQZ9sYxIZ-N_q2wCE,8593
42
+ cu_cli/core/schema.py,sha256=fhUeHlenZQhnj50HrE-srOv2ILsaNB8bWkgpTKWu11E,626
43
+ cu_cli/resources/__init__.py,sha256=m1srM72w5rc2dYn8wXIkDYQ8TBPIIXMax2Q0I2vVysM,142
44
+ cu_cli/resources/azd_template/README.md,sha256=Cqwb0bg29DwIy6CHyhFakq3CN2h3kvmKtK-sLG38UIM,8373
45
+ cu_cli/resources/azd_template/azure.yaml,sha256=e9vG-M9C_BSFulLATX7Qw6t4zVF9SJKxJ1p7gGrDFmc,742
46
+ cu_cli/resources/azd_template/hooks/postprovision.ps1,sha256=8lZW8VvzAHlco9KOrrYykyFn8dKHx0Kqc2BFQNGGoUg,14422
47
+ cu_cli/resources/azd_template/hooks/postprovision.sh,sha256=cx6FpAcILRTi2UL7_prI6CcAzHuzdgbMpvj7j6E6HKg,12414
48
+ cu_cli/resources/azd_template/infra/main.bicep,sha256=rN2OsHfYpMTamutZdv1u1yvxLppfuIWnRwGzyIldkqU,5185
49
+ cu_cli/resources/azd_template/infra/main.parameters.json,sha256=m9ptgHue5J5GinAvif3uo-Vg7kxqlhZ5tel7Mai0_cQ,773
50
+ cu_cli/resources/azd_template/infra/models.json,sha256=N1F-Xz3GaBn2H1p7uKzhkhKCQV8QVR0t76XD6wmFtXA,3
51
+ cu_cli/resources/azd_template/infra/modules/foundry.bicep,sha256=YTKRran5peWzOJUmoNKgGGxLlBhVJDHLLDHCRE-awB8,3683
52
+ cu_cli-0.1.0b1.dist-info/METADATA,sha256=sI_uT5jbZH23FlPAPlGH6s83q2WTgi4mPYFQobHKZRE,15116
53
+ cu_cli-0.1.0b1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
54
+ cu_cli-0.1.0b1.dist-info/entry_points.txt,sha256=kLZwQxUM-rTAzoAR_ti8P-R8NB561gEh-pN1lQgiQsU,64
55
+ cu_cli-0.1.0b1.dist-info/top_level.txt,sha256=AxwNJjvjn81SAkSkB21ljPbi25_KLdKuLfKlVg8ep44,7
56
+ cu_cli-0.1.0b1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ cu = cu_cli.cli:main
3
+ cu-cli = cu_cli.cli:main
@@ -0,0 +1 @@
1
+ cu_cli