Skip to content

Commit 76c774f

Browse files
Merge pull request #535 from jamesbroadhead/ace-review-fixes-main
fix: small correctness/security cleanups in apps-python / python-sdk examples
2 parents 93cb4e3 + 8662a46 commit 76c774f

5 files changed

Lines changed: 69 additions & 39 deletions

File tree

.github/workflows/ci.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,28 @@ permissions:
88
contents: read
99

1010
jobs:
11+
skills-unit-tests:
12+
name: databricks-skills unit tests
13+
runs-on: linux-ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
16+
17+
- uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
18+
with:
19+
version: "0.11.4"
20+
21+
- name: Run databricks-skills unit tests
22+
run: |
23+
if [ -d databricks-skills/.tests ]; then
24+
uvx --python 3.11 \
25+
--with pytest \
26+
--with databricks-sdk \
27+
--with requests \
28+
pytest databricks-skills/.tests/ -m "not integration" -v
29+
else
30+
echo "databricks-skills/.tests/ not present on this branch; skipping."
31+
fi
32+
1133
lint:
1234
name: Lint & Format
1335
runs-on: linux-ubuntu-latest

databricks-skills/databricks-apps-python/examples/fm-minimal-chat.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616
export DATABRICKS_TOKEN="dapi..."
1717
export DATABRICKS_SERVING_BASE_URL="https://<workspace>/serving-endpoints"
1818
export DATABRICKS_MODEL="<endpoint-name>" # See databricks-model-serving
19-
streamlit run 2-minimal-chat-app.py
19+
streamlit run fm-minimal-chat.py
2020
2121
Databricks Apps Deployment:
2222
1. Create app.yaml:
23-
command: ["streamlit", "run", "2-minimal-chat-app.py"]
23+
command: ["streamlit", "run", "fm-minimal-chat.py"]
2424
env:
2525
- name: DATABRICKS_SERVING_BASE_URL
2626
value: "https://<workspace>/serving-endpoints"

databricks-skills/databricks-apps-python/examples/fm-parallel-calls.py

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -224,42 +224,44 @@ def check_audience_fit(client: OpenAI, text: str) -> Dict[str, Any]:
224224
time_saved = (total_latency / 1000) - total_time
225225
print(f"\n{'='*60}")
226226
print(f"Time saved vs serial execution: {time_saved:.2f}s")
227-
print(f"Speedup: {(total_latency/1000) / total_time:.1f}×")
227+
if total_time > 0:
228+
print(f"Speedup: {(total_latency/1000) / total_time:.1f}×")
229+
else:
230+
print("Speedup: N/A (total_time below resolution)")
228231
print(f"{'='*60}")
229232

230233

231234
# =============================================================================
232235
# Production Best Practices
233236
# =============================================================================
234-
"""
235-
Best practices from databricksters-check-and-pub:
236-
237-
1. Configurable concurrency
238-
- Use LLM_MAX_CONCURRENCY env var (default: 5 in the production app)
239-
- Balance throughput vs rate limits
240-
- Too high = rate limit errors
241-
- Too low = underutilized resources
242-
243-
2. Error handling
244-
- Capture exceptions per job
245-
- Return None for failed jobs
246-
- Collect error messages for debugging
247-
- Continue execution even if some jobs fail
248-
249-
3. Bounded execution
250-
- Only parallelize independent checks
251-
- Cap concurrency with an env var rather than firing unlimited requests
252-
- Keep the job contract simple: name -> (callable, args, kwargs)
253-
254-
4. When to use parallel calls
255-
- Multiple independent evaluations of same content
256-
- Batch processing multiple documents
257-
- A/B testing different prompts
258-
- Multi-aspect analysis
259-
260-
5. When NOT to use parallel calls
261-
- Dependent/sequential operations
262-
- Single evaluation needed
263-
- Rate limits are very strict
264-
- Debugging (use serial for easier troubleshooting)
265-
"""
237+
#
238+
# Best practices from databricksters-check-and-pub:
239+
#
240+
# 1. Configurable concurrency
241+
# - Use LLM_MAX_CONCURRENCY env var (default: 5 in the production app)
242+
# - Balance throughput vs rate limits
243+
# - Too high = rate limit errors
244+
# - Too low = underutilized resources
245+
#
246+
# 2. Error handling
247+
# - Capture exceptions per job
248+
# - Return None for failed jobs
249+
# - Collect error messages for debugging
250+
# - Continue execution even if some jobs fail
251+
#
252+
# 3. Bounded execution
253+
# - Only parallelize independent checks
254+
# - Cap concurrency with an env var rather than firing unlimited requests
255+
# - Keep the job contract simple: name -> (callable, args, kwargs)
256+
#
257+
# 4. When to use parallel calls
258+
# - Multiple independent evaluations of same content
259+
# - Batch processing multiple documents
260+
# - A/B testing different prompts
261+
# - Multi-aspect analysis
262+
#
263+
# 5. When NOT to use parallel calls
264+
# - Dependent/sequential operations
265+
# - Single evaluation needed
266+
# - Rate limits are very strict
267+
# - Debugging (use serial for easier troubleshooting)

databricks-skills/databricks-apps-python/examples/llm_config.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,10 @@ def get_databricks_bearer_token(
218218
access_token = payload.get("access_token")
219219
expires_in = int(payload.get("expires_in", 300))
220220
if not access_token:
221+
payload_keys = sorted(payload.keys()) if isinstance(payload, dict) else []
221222
raise DatabricksLLMConfigError(
222-
f"Token endpoint response is missing access_token: {payload}"
223+
"Token endpoint response is missing access_token "
224+
f"(keys present: {payload_keys})"
223225
)
224226

225227
expires_at = int(time.time()) + expires_in
@@ -278,8 +280,7 @@ def validate_databricks_llm_config(
278280
if response.status_code >= 400:
279281
raise DatabricksLLMConfigError(
280282
f"Failed to validate DATABRICKS_MODEL={config.model!r} in workspace "
281-
f"{config.workspace_host} (HTTP {response.status_code}). "
282-
f"Response: {response.text[:300]}"
283+
f"{config.workspace_host} (HTTP {response.status_code})."
283284
)
284285

285286
_validation_cache[cache_key] = int(time.time()) + VALIDATION_TTL_SECONDS

databricks-skills/databricks-python-sdk/examples/5-serving-and-vector-search.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,15 @@
168168

169169

170170
# Query with embedding vector directly
171+
# query_vector must be a list[float] whose length matches your index's
172+
# embedding dimension (e.g. 768 for bge-small, 1024 for bge-large, 1536 for
173+
# text-embedding-3-small / ada-002). The [0.0] * N below is a stand-in;
174+
# replace with the actual vector returned by your embedding model.
175+
query_vector = [0.0] * 768
171176
results = w.vector_search_indexes.query_index(
172177
index_name="main.default.my_index",
173178
columns=["id", "text"],
174-
query_vector=[0.1, 0.2, 0.3, ...], # Your embedding vector
179+
query_vector=query_vector,
175180
num_results=10
176181
)
177182

0 commit comments

Comments
 (0)