Skip to content

Commit 55d2b15

Browse files
committed
Add sync examples
1 parent 07f8f2b commit 55d2b15

File tree

6 files changed

+367
-0
lines changed

6 files changed

+367
-0
lines changed

examples/sync/chat/__init__.py

Whitespace-only changes.

examples/sync/chat/history.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/usr/bin/env python3
2+
3+
from __future__ import annotations
4+
5+
from yandex_cloud_ml_sdk import YCloudML
6+
7+
8+
def get_model(sdk: YCloudML):
9+
models = sdk.chat.completions.list()
10+
i = 0
11+
print('You have access to the following models:')
12+
for i, model in enumerate(models):
13+
print(f" [{i:2}] {model.uri}")
14+
15+
raw_number = input(f"Please, input model number from 0 to {i}: ")
16+
number = int(raw_number)
17+
return models[number]
18+
19+
20+
def main() -> None:
21+
sdk = YCloudML(folder_id='b1ghsjum2v37c2un8h64')
22+
sdk.setup_default_logging()
23+
24+
model = get_model(sdk)
25+
model = model.configure(temperature=0.5)
26+
27+
context = []
28+
while True:
29+
request = input("Please input request for model: ")
30+
context.append(request)
31+
32+
chunk = None
33+
# I am using run_stream here for extra beuty,
34+
# this is not different from just "run" when we talking about context
35+
for chunk in model.run_stream(context):
36+
print(chunk[0].delta, end="", flush=True)
37+
print()
38+
assert chunk # to please static type checker
39+
40+
# We are putting model answer to context to send it to the next
41+
# request;
42+
# We could use last chunk object because it have ".text" attribute which
43+
# contains full model answer
44+
context.append(chunk)
45+
46+
47+
if __name__ == '__main__':
48+
main()

examples/sync/chat/reasoning.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/usr/bin/env python3
2+
3+
from __future__ import annotations
4+
5+
from yandex_cloud_ml_sdk import YCloudML
6+
7+
8+
def get_model(sdk: YCloudML):
9+
models = sdk.chat.completions.list()
10+
i = 0
11+
print('You have access to the following models:')
12+
for i, model in enumerate(models):
13+
print(f" [{i:2}] {model.uri}")
14+
15+
raw_number = input(f"Please, input model number from 0 to {i}: ")
16+
number = int(raw_number)
17+
return models[number]
18+
19+
20+
def main() -> None:
21+
sdk = YCloudML(folder_id='b1ghsjum2v37c2un8h64')
22+
sdk.setup_default_logging()
23+
24+
# This is how to create model object
25+
model = sdk.chat.completions('qwen3-235b-a22b-fp8')
26+
# But in this example we will get it via .list method
27+
model = get_model(sdk)
28+
29+
request = "What it would be 11!?"
30+
31+
model = model.configure(temperature=0, reasoning_mode='medium')
32+
33+
result = model.run(request)
34+
print(f"Request: {request}")
35+
print(f"Reasoinig text: {result.reasoning_text}")
36+
print(f"Result text: {result.text}")
37+
38+
print()
39+
print(f"Streaming request: {request}")
40+
41+
model = model.configure(reasoning_mode='high')
42+
reasoning_started = False
43+
result_started = False
44+
45+
for chunk in model.run_stream(request):
46+
delta: str | None = None
47+
# NB: there is very important difference between reasoning_delta and reasoning_text,
48+
# like chunk.text/chunk.delta, look into stream.py example file for details
49+
if delta := chunk.choices[0].reasoning_delta:
50+
if not reasoning_started:
51+
print('Streaming reasoning text: ')
52+
53+
reasoning_started = True
54+
55+
elif delta := chunk.choices[0].delta:
56+
if not result_started:
57+
print()
58+
print('Streaming result text: ')
59+
result_started = True
60+
61+
if delta:
62+
print(delta, end="", flush=True)
63+
64+
# you could reset to default reasoning mode
65+
model = model.configure(reasoning_mode=None)
66+
result = model.run(request)
67+
print(f"Reasoinig text with default resoning mode: {result.reasoning_text}")
68+
69+
70+
if __name__ == '__main__':
71+
main()

examples/sync/chat/run.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#!/usr/bin/env python3
2+
3+
from __future__ import annotations
4+
5+
import pprint
6+
7+
from yandex_cloud_ml_sdk import YCloudML
8+
9+
10+
def get_model(sdk: YCloudML):
11+
models = sdk.chat.completions.list()
12+
i = 0
13+
print('You have access to the following models:')
14+
for i, model in enumerate(models):
15+
print(f" [{i:2}] {model.uri}")
16+
17+
raw_number = input(f"Please, input model number from 0 to {i}: ")
18+
number = int(raw_number)
19+
return models[number]
20+
21+
22+
def main() -> None:
23+
sdk = YCloudML(folder_id='b1ghsjum2v37c2un8h64')
24+
sdk.setup_default_logging()
25+
26+
# This is how to create model object
27+
model = sdk.chat.completions('qwen3-235b-a22b-fp8')
28+
# But in this example we will get it via .list method
29+
model = get_model(sdk)
30+
31+
request = "How to calculate the Hirsch index in O(N)"
32+
33+
model = model.configure(temperature=0.5)
34+
35+
result = model.run(request)
36+
37+
print('You could inspect the fields which have the result structure:')
38+
pprint.pprint(result)
39+
print('\n')
40+
41+
print('Or just access the "text/content" field')
42+
print(result.text)
43+
44+
# NB: text and content is a synonyms
45+
assert result.text == result.content
46+
47+
model = model.configure(max_tokens=10)
48+
result = model.run(request)
49+
assert result.finish_reason.name == 'LENGTH'
50+
# status field is a synonym for finish_reason, but with names consistent with
51+
# another parts ofr yandex_cloud_ml_sdk
52+
assert result.status.name == 'TRUNCATED_FINAL'
53+
54+
55+
if __name__ == '__main__':
56+
main()

examples/sync/chat/stream.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#!/usr/bin/env python3
2+
3+
from __future__ import annotations
4+
5+
from yandex_cloud_ml_sdk import YCloudML
6+
7+
8+
def clear():
9+
# We are clearing the screen with this ascii combination;
10+
# it will probably work only at the linux terminals
11+
print(chr(27) + "[2J")
12+
13+
14+
def get_model(sdk: YCloudML):
15+
models = sdk.chat.completions.list()
16+
i = 0
17+
print('You have access to the following models:')
18+
for i, model in enumerate(models):
19+
print(f" [{i:2}] {model.uri}")
20+
21+
raw_number = input(f"Please, input model number from 0 to {i}: ")
22+
number = int(raw_number)
23+
return models[number]
24+
25+
26+
def main() -> None:
27+
sdk = YCloudML(folder_id='b1ghsjum2v37c2un8h64')
28+
sdk.setup_default_logging()
29+
30+
# This is how to create model object
31+
model = sdk.chat.completions('qwen3-235b-a22b-fp8')
32+
# But in this example we will get it via .list method
33+
model = get_model(sdk)
34+
35+
model = model.configure(temperature=0.5)
36+
37+
request = "How to calculate the Hirsch index in O(N)"
38+
39+
chunk = None
40+
41+
for chunk in model.run_stream(request):
42+
clear()
43+
print(f"{request}:")
44+
print(chunk.text)
45+
46+
# chunk[0] is a shortcut for chunk.choices[0]:
47+
choice = chunk[0]
48+
assert choice == chunk[0] == chunk.choices[0]
49+
50+
# chunk.text is a shortcut for chunk[0].text:
51+
assert chunk.text == choice.text
52+
53+
# There is very important difference between choice.text and
54+
# choice.delta:
55+
# * choice.text contains a constantly increasing PREFIX of generated text,
56+
# like in other parts of yandex-cloud-ml-sdk
57+
# * choice.delta contains only newly generated text delta in openai-streaming style
58+
clear()
59+
print(f"{request}:")
60+
for chunk in model.run_stream(request):
61+
print(chunk[0].delta, end="", flush=True)
62+
print()
63+
64+
assert chunk # to make type checker happy
65+
# NB: Some of the models have a usage field in the last chunk;
66+
# qwen3-235b-a22b-fp8 does have it:
67+
print("{chunk.usage=}")
68+
69+
model = model.configure(max_tokens=10)
70+
print('\n')
71+
print("Showcase for 'length' finish reason:")
72+
for chunk in model.run_stream(request):
73+
print(chunk)
74+
75+
assert chunk.finish_reason.name == 'LENGTH'
76+
# status field is a synonym for finish_reason, but with names consistent with
77+
# another parts of yandex_cloud_ml_sdk
78+
assert chunk.status.name == 'TRUNCATED_FINAL'
79+
80+
81+
if __name__ == '__main__':
82+
main()
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#!/usr/bin/env python3
2+
3+
from __future__ import annotations
4+
5+
import json
6+
7+
import pydantic
8+
9+
from yandex_cloud_ml_sdk import YCloudML
10+
11+
12+
class Venue(pydantic.BaseModel):
13+
date: str
14+
place: str
15+
16+
17+
@pydantic.dataclasses.dataclass
18+
class VenueDataclass:
19+
date: str
20+
place: str
21+
month: str
22+
23+
24+
def get_model(sdk: YCloudML):
25+
models = sdk.chat.completions.list()
26+
i = 0
27+
print('You have access to the following models:')
28+
for i, model in enumerate(models):
29+
print(f" [{i:2}] {model.uri}")
30+
31+
raw_number = input(f"Please, input model number from 0 to {i}: ")
32+
number = int(raw_number)
33+
return models[number]
34+
35+
36+
def main() -> None:
37+
sdk = YCloudML(folder_id='b1ghsjum2v37c2un8h64')
38+
sdk.setup_default_logging()
39+
40+
model = get_model(sdk)
41+
text = (
42+
'The conference will take place from May 10th to 12th, 2023, '
43+
'at 30 Avenue Corentin Cariou in Paris, France.'
44+
)
45+
context = [
46+
{'role': 'system', 'text': 'Extract the date and venue information'},
47+
{'role': 'user', 'text': text},
48+
]
49+
50+
# We could as model to return data just with json format, model will
51+
# figure out format by itself:
52+
model = model.configure(response_format='json')
53+
result = model.run(context)
54+
print('Any JSON:', result[0].text)
55+
56+
# Now, if you need not just JSON, but a parsed Python structure, you will need to parse it.
57+
# Be aware that you may need to handle parsing exceptions in case the model returns incorrect json.
58+
# This could happen, for example, if you exceed the token limit.
59+
try:
60+
data = json.loads(result.text)
61+
print("Parsed JSON:", data)
62+
63+
bad_text = result.text[:5]
64+
json.loads(bad_text)
65+
except json.JSONDecodeError as e:
66+
print("JSON parsing error:", e)
67+
68+
# You could use not only .run, but .run_stream as well as other methods too:
69+
print('Any JSON in streaming:')
70+
for partial_result in model.run_stream(context):
71+
print(f" {partial_result.text or '<EMPTY>'}")
72+
73+
# NB: For each example, I am trying to make slightly different format to show a difference at print results.
74+
# We could pass a raw json schema:
75+
model = model.configure(response_format={
76+
"name": 'foo',
77+
"json_schema": {
78+
"properties": {
79+
"DATE": {
80+
"title": "Date",
81+
"type": "string"
82+
},
83+
"PLACE": {
84+
"title": "Place",
85+
"type": "string"
86+
}
87+
},
88+
"required": ["DATE", "PLACE"],
89+
"title": "Venue",
90+
"type": "object"
91+
}
92+
})
93+
result = model.run(context)
94+
print('JSONSchema from raw jsonschema:', result[0].text)
95+
96+
# Also we could use pydantic.BaseModel descendant to describe JSONSchema for
97+
# structured output:
98+
model = model.configure(response_format=Venue)
99+
result = model.run(context)
100+
print('JSONSchema from Pydantic model:', result[0].text)
101+
102+
# Lastly we could pass pydantic-dataclass:
103+
assert pydantic.__version__ > "2"
104+
model = model.configure(response_format=VenueDataclass)
105+
result = model.run(context)
106+
print('JSONSchema from Pydantic dataclass:', result[0].text)
107+
108+
109+
if __name__ == '__main__':
110+
main()

0 commit comments

Comments
 (0)