Skip to content

Commit d4f31cd

Browse files
authored
docs: update user-guide.md of aicore, destination and object store modules (#10)
1 parent eaeb333 commit d4f31cd

4 files changed

Lines changed: 378 additions & 5 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
![Build status](https://github.com/SAP/cloud-sdk-python/workflows/Build/badge.svg) [![REUSE status](https://api.reuse.software/badge/github.com/SAP/cloud-sdk-python)](https://api.reuse.software/info/github.com/SAP/cloud-sdk-python)
1+
[![Build & Package](https://github.com/SAP/cloud-sdk-python/actions/workflows/build.yaml/badge.svg)](https://github.com/SAP/cloud-sdk-python/actions/workflows/build.yaml) [![REUSE status](https://api.reuse.software/badge/github.com/SAP/cloud-sdk-python)](https://api.reuse.software/info/github.com/SAP/cloud-sdk-python)
22

33
# SAP Cloud SDK for Python
44

Lines changed: 373 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,373 @@
1+
# AI Core User Guide
2+
3+
This module provides utilities to configure SAP AI Core credentials for use with AI frameworks like LiteLLM. It automatically loads credentials from mounted secrets or environment variables and sets them up for seamless integration with AI Core services.
4+
5+
## Installation
6+
7+
The AI Core module is part of the SAP Cloud SDK for Python and is automatically available when the SDK is installed.
8+
9+
## Import
10+
11+
```python
12+
from sap_cloud_sdk.aicore import set_aicore_config
13+
```
14+
15+
---
16+
17+
## Quick Start
18+
19+
### Basic Setup
20+
21+
Use `set_aicore_config()` to automatically load and configure AI Core credentials:
22+
23+
```python
24+
from sap_cloud_sdk.aicore import set_aicore_config
25+
26+
# Load credentials and configure environment for AI Core
27+
set_aicore_config()
28+
29+
# Now use LiteLLM with AI Core
30+
from litellm import completion
31+
32+
response = completion(
33+
model="sap/gpt-4",
34+
messages=[{"role": "user", "content": "Hello!"}]
35+
)
36+
```
37+
38+
### Custom Instance
39+
40+
If you have multiple AI Core instances, specify the instance name:
41+
42+
```python
43+
from sap_cloud_sdk.aicore import set_aicore_config
44+
45+
# Load credentials for a specific AI Core instance
46+
set_aicore_config(instance_name="aicore-production")
47+
```
48+
49+
---
50+
51+
## What It Does
52+
53+
The `set_aicore_config()` function:
54+
55+
1. **Loads credentials** from mounted secrets (Kubernetes) or environment variables
56+
2. **Configures environment variables** for LiteLLM to use AI Core
57+
3. **Normalizes URLs** by adding required suffixes (`/oauth/token` for auth, `/v2` for base URL)
58+
4. **Sets resource group** (defaults to "default" if not specified)
59+
60+
### Credentials Loaded
61+
62+
The function loads and configures these credentials:
63+
64+
- **AICORE_CLIENT_ID** - OAuth2 client ID for authentication
65+
- **AICORE_CLIENT_SECRET** - OAuth2 client secret
66+
- **AICORE_AUTH_URL** - Authentication endpoint (auto-appends `/oauth/token` if needed)
67+
- **AICORE_BASE_URL** - AI Core service base URL (auto-appends `/v2` if needed)
68+
- **AICORE_RESOURCE_GROUP** - Resource group name (defaults to "default")
69+
70+
---
71+
72+
## Configuration
73+
74+
### Cloud Mode (Mounted Secrets)
75+
76+
In Kubernetes environments, secrets are automatically loaded from:
77+
78+
```
79+
/etc/secrets/appfnd/aicore/{instance_name}/
80+
├── clientid # OAuth2 client ID
81+
├── clientsecret # OAuth2 client secret
82+
├── url # Authentication server URL
83+
└── serviceurls # JSON file with AI_API_URL field
84+
```
85+
86+
**serviceurls file format:**
87+
```json
88+
{
89+
"AI_API_URL": "https://api.ai.prod.eu-central-1.aws.ml.hana.ondemand.com"
90+
}
91+
```
92+
93+
### Environment Variable Fallback
94+
95+
If mounted secrets are not available, the function falls back to environment variables:
96+
97+
```bash
98+
# Authentication credentials
99+
export AICORE_CLIENT_ID="your-client-id"
100+
export AICORE_CLIENT_SECRET="your-client-secret"
101+
102+
# Service endpoints
103+
export AICORE_AUTH_URL="https://your-subdomain.authentication.eu10.hana.ondemand.com/oauth/token"
104+
export AICORE_BASE_URL="https://api.ai.prod.eu-central-1.aws.ml.hana.ondemand.com/v2"
105+
106+
# Optional: Resource group (defaults to "default")
107+
export AICORE_RESOURCE_GROUP="my-resource-group"
108+
```
109+
110+
---
111+
112+
## Usage with LiteLLM
113+
114+
After calling `set_aicore_config()`, LiteLLM automatically uses the configured AI Core credentials:
115+
116+
```python
117+
from sap_cloud_sdk.aicore import set_aicore_config
118+
from litellm import completion
119+
120+
# Configure AI Core
121+
set_aicore_config()
122+
123+
# Use AI Core models through LiteLLM
124+
response = completion(
125+
model="sap/gpt-4",
126+
messages=[
127+
{"role": "system", "content": "You are a helpful assistant."},
128+
{"role": "user", "content": "What is SAP AI Core?"}
129+
]
130+
)
131+
132+
print(response.choices[0].message.content)
133+
```
134+
135+
### Streaming Responses
136+
137+
```python
138+
from sap_cloud_sdk.aicore import set_aicore_config
139+
from litellm import completion
140+
141+
set_aicore_config()
142+
143+
response = completion(
144+
model="sap/gpt-4",
145+
messages=[{"role": "user", "content": "Tell me a story"}],
146+
stream=True
147+
)
148+
149+
for chunk in response:
150+
if chunk.choices[0].delta.content:
151+
print(chunk.choices[0].delta.content, end="")
152+
```
153+
154+
### Using Different Models
155+
156+
```python
157+
from sap_cloud_sdk.aicore import set_aicore_config
158+
from litellm import completion, embedding
159+
160+
set_aicore_config()
161+
162+
# Chat completion
163+
chat_response = completion(
164+
model="sap/gpt-4",
165+
messages=[{"role": "user", "content": "Hello!"}]
166+
)
167+
168+
# Text embeddings
169+
embedding_response = embedding(
170+
model="sap/text-embedding-ada-002",
171+
input=["Hello world", "How are you?"]
172+
)
173+
```
174+
175+
---
176+
177+
## Multiple AI Core Instances
178+
179+
If you have multiple AI Core instances (e.g., development, staging, production), specify the instance name:
180+
181+
```python
182+
from sap_cloud_sdk.aicore import set_aicore_config
183+
184+
# Development environment
185+
set_aicore_config(instance_name="aicore-dev")
186+
187+
# Production environment
188+
set_aicore_config(instance_name="aicore-prod")
189+
```
190+
191+
Each instance should have its own mounted secrets or environment variables.
192+
193+
---
194+
195+
## URL Normalization
196+
197+
The function automatically normalizes URLs to ensure compatibility:
198+
199+
### Authentication URL
200+
- **Input**: `https://subdomain.authentication.region.hana.ondemand.com`
201+
- **Output**: `https://subdomain.authentication.region.hana.ondemand.com/oauth/token`
202+
203+
### Base URL
204+
- **Input**: `https://api.ai.prod.region.aws.ml.hana.ondemand.com`
205+
- **Output**: `https://api.ai.prod.region.aws.ml.hana.ondemand.com/v2`
206+
207+
---
208+
209+
## Complete Example
210+
211+
```python
212+
from sap_cloud_sdk.aicore import set_aicore_config
213+
from litellm import completion
214+
import logging
215+
216+
# Configure logging to see credential loading messages
217+
logging.basicConfig(level=logging.INFO)
218+
219+
# Load and configure AI Core credentials
220+
try:
221+
set_aicore_config(instance_name="aicore-instance")
222+
print("AI Core configuration successful")
223+
except Exception as e:
224+
print(f"Failed to configure AI Core: {e}")
225+
exit(1)
226+
227+
# Use AI Core through LiteLLM
228+
try:
229+
response = completion(
230+
model="sap/gpt-4",
231+
messages=[
232+
{"role": "system", "content": "You are a helpful AI assistant."},
233+
{"role": "user", "content": "Explain SAP AI Core in one sentence."}
234+
],
235+
temperature=0.7,
236+
max_tokens=100
237+
)
238+
239+
print(f"Response: {response.choices[0].message.content}")
240+
241+
except Exception as e:
242+
print(f"AI Core request failed: {e}")
243+
```
244+
245+
---
246+
247+
## Logging
248+
249+
The module uses Python's standard logging to provide visibility into the credential loading process:
250+
251+
```python
252+
import logging
253+
from sap_cloud_sdk.aicore import set_aicore_config
254+
255+
# Enable INFO logging to see which credentials were loaded
256+
logging.basicConfig(level=logging.INFO)
257+
258+
set_aicore_config()
259+
# Logs will show:
260+
# INFO:sap_cloud_sdk.aicore:Loaded AICORE_CLIENT_ID from file: /etc/secrets/appfnd/aicore/aicore-instance/clientid
261+
# INFO:sap_cloud_sdk.aicore:Loaded AICORE_CLIENT_SECRET from file: /etc/secrets/appfnd/aicore/aicore-instance/clientsecret
262+
# etc.
263+
```
264+
265+
---
266+
267+
## Error Handling
268+
269+
Always handle potential configuration errors:
270+
271+
```python
272+
from sap_cloud_sdk.aicore import set_aicore_config
273+
import logging
274+
275+
logging.basicConfig(level=logging.WARNING)
276+
277+
try:
278+
set_aicore_config()
279+
except Exception as e:
280+
logging.error(f"Failed to configure AI Core: {e}")
281+
# Handle the error appropriately
282+
# - Use default/fallback configuration
283+
# - Notify monitoring system
284+
# - Exit gracefully
285+
```
286+
287+
---
288+
289+
## Best Practices
290+
291+
1. **Call once at startup**: Configure AI Core credentials once at application startup, before making any LiteLLM calls
292+
293+
2. **Use instance names**: When deploying to multiple environments, use descriptive instance names:
294+
```python
295+
set_aicore_config(instance_name="aicore-prod")
296+
```
297+
298+
3. **Enable logging**: Use logging to troubleshoot credential loading issues:
299+
```python
300+
logging.basicConfig(level=logging.INFO)
301+
```
302+
303+
4. **Handle errors gracefully**: Wrap configuration in try-except to handle missing credentials:
304+
```python
305+
try:
306+
set_aicore_config()
307+
except Exception as e:
308+
# Fallback or exit
309+
pass
310+
```
311+
312+
5. **Keep secrets secure**: Never hardcode credentials; always use mounted secrets or environment variables
313+
314+
---
315+
316+
## Troubleshooting
317+
318+
### Credentials Not Found
319+
320+
If you see warnings about missing credentials:
321+
322+
```
323+
WARNING:sap_cloud_sdk.aicore:No value found for AICORE_CLIENT_ID, using default
324+
```
325+
326+
**Solution**: Ensure either:
327+
- Mounted secrets exist at `/etc/secrets/appfnd/aicore/{instance_name}/`
328+
- Environment variables are set with the correct naming pattern
329+
330+
### Authentication Errors
331+
332+
If LiteLLM fails with authentication errors:
333+
334+
1. **Check credentials are loaded**: Enable INFO logging to verify credentials were found
335+
2. **Verify URLs**: Ensure AICORE_AUTH_URL and AICORE_BASE_URL are correct
336+
3. **Check resource group**: Verify AICORE_RESOURCE_GROUP matches your AI Core setup
337+
338+
### Wrong Instance
339+
340+
If credentials from the wrong instance are loaded:
341+
342+
```python
343+
# Explicitly specify the correct instance name
344+
set_aicore_config(instance_name="correct-instance-name")
345+
```
346+
347+
---
348+
349+
## Integration with Telemetry
350+
351+
The AI Core configuration function includes built-in telemetry support using the SDK's telemetry module. All calls to `set_aicore_config()` are automatically tracked with metrics.
352+
353+
To enable telemetry tracking:
354+
355+
```python
356+
from sap_cloud_sdk.core.telemetry import auto_instrument
357+
from sap_cloud_sdk.aicore import set_aicore_config
358+
359+
# Enable auto-instrumentation
360+
auto_instrument()
361+
362+
# Configuration calls are now tracked
363+
set_aicore_config()
364+
```
365+
366+
---
367+
368+
## Notes
369+
370+
- The `set_aicore_config()` function sets environment variables that persist for the lifetime of the Python process
371+
- If you need to switch between multiple AI Core instances at runtime, call `set_aicore_config()` with different instance names
372+
- The function is safe to call multiple times; subsequent calls will overwrite the environment variables
373+
- Resource group defaults to "default" if not specified in secrets or environment variables

src/sap_cloud_sdk/destination/user-guide.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ The fragment client produced by `create_fragment_client()` exposes the following
8181
class FragmentClient:
8282
def get_instance_fragment(self, name: str) -> Optional[Fragment]: ...
8383
def get_subaccount_fragment(self, name: str, access_strategy: AccessStrategy = AccessStrategy.SUBSCRIBER_FIRST, tenant: Optional[str] = None) -> Optional[Fragment]: ...
84-
def list_instance_fragments(self, filter: Optional[ListOptions] = None) -> PagedResult[Fragment]: ...
85-
def list_subaccount_fragments(self, access_strategy: AccessStrategy = AccessStrategy.SUBSCRIBER_FIRST, tenant: Optional[str] = None, filter: Optional[ListOptions] = None) -> PagedResult[Fragment]: ...
84+
def list_instance_fragments(self) -> List[Fragment]: ...
85+
def list_subaccount_fragments(self, access_strategy: AccessStrategy = AccessStrategy.SUBSCRIBER_FIRST, tenant: Optional[str] = None) -> List[Fragment]: ...
8686
def create_fragment(self, fragment: Fragment, level: Optional[Level] = Level.SUB_ACCOUNT) -> None: ...
8787
def update_fragment(self, fragment: Fragment, level: Optional[Level] = Level.SUB_ACCOUNT) -> None: ...
8888
def delete_fragment(self, name: str, level: Optional[Level] = Level.SUB_ACCOUNT) -> None: ...

0 commit comments

Comments
 (0)