Skip to content

Commit 047a66a

Browse files
authored
Merge branch 'main' into nathsudi/npu-profile-main
2 parents 96d281b + 97fe685 commit 047a66a

File tree

35 files changed

+573
-584
lines changed

35 files changed

+573
-584
lines changed

.github/workflows/docs-reusable-workflow.yaml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
# SPDX-FileCopyrightText: (C) 2025 Intel Corporation
33
# SPDX-License-Identifier: Apache-2.0
44

5-
name: 'Build Documentation'
5+
name: "Build Documentation"
66

7-
on: # yamllint disable-line rule:truthy rule:line-length
7+
on: # yamllint disable-line rule:truthy rule:line-length
88
workflow_call:
99
inputs:
1010
docs_directory:
@@ -33,14 +33,13 @@ permissions:
3333
jobs:
3434
build-documentation:
3535
permissions:
36-
contents: read # minimal privilege required
36+
contents: read # minimal privilege required
3737
runs-on: ubuntu-latest
3838
env:
3939
DOCS_DIR: ${{ inputs.docs_directory }}
4040
steps:
41-
4241
- name: Checkout code
43-
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
42+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
4443
with:
4544
# Fetch all history, otherwise sporadic issue with missing tags
4645
fetch-depth: 0

.github/workflows/documentation-check.yaml

Lines changed: 132 additions & 104 deletions
Large diffs are not rendered by default.

CONTRIBUTING.md

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
# Edge-AI-Suites Contributor Guide
33

4-
The following are guidelines for contributing to the Edge AI Suites project, including the code of conduct, submitting issues, and contributing code.
4+
The following are guidelines for contributing to the Edge AI Suites project, including the code of conduct, submitting issues, and contributing code.
55

66
# Table of Contents
77

@@ -15,37 +15,44 @@ The following are guidelines for contributing to the Edge AI Suites project, inc
1515

1616
# Code of Conduct
1717

18-
This project and everyone participating in it are governed by the [`CODE_OF_CONDUCT`](CODE_OF_CONDUCT.md) document. By participating, you are expected to adhere to this code.
18+
This project and everyone participating in it are governed by the [`CODE_OF_CONDUCT`](CODE_OF_CONDUCT.md) document. By participating, you are expected to adhere to this code.
1919

20-
# Security
20+
# Security
2121

22-
Read the [`Security Policy`](SECURITY.md).
22+
Read the [`Security Policy`](SECURITY.md).
2323

2424
# Get Started
2525

26-
Clone the repository and follow the [`README`](README.md) to get started with the sample applications of interest.
26+
Clone the repository and follow the [`README`](README.md) or
27+
[documentation's](https://docs.openedgeplatform.intel.com/) "Get Started" of the chosen
28+
applications.
2729

2830
```
2931
git clone https://github.com/open-edge-platform/edge-ai-suites.git
3032
cd edge-ai-suites
3133
```
34+
Note that you do not need to clone the entire repository. You can clone just the portion you
35+
are interested with. To see how ti do it, check out the
36+
[Contributing to Open Edge Platform](https://docs.openedgeplatform.intel.com/canonical/OEP-articles/contribution-guide.html#repository-cloning-partial-cloning)
37+
article.
38+
3239

3340
# How to Contribute
3441

3542
## Contribute Code Changes
3643

37-
> If you want to help improve Edge AI Suites, choose one of the issues reported in [`GitHub Issues`](https://github.com/open-edge-platform/edge-ai-suites/issues) and create a [`Pull Request`](https://github.com/open-edge-platform/edge-ai-suites/pulls) to address it.
44+
> If you want to help improve Edge AI Suites, choose one of the issues reported in [`GitHub Issues`](https://github.com/open-edge-platform/edge-ai-suites/issues) and create a [`Pull Request`](https://github.com/open-edge-platform/edge-ai-suites/pulls) to address it.
3845
> Note: Please check that the change hasn't been implemented before you start working on it.
3946
4047
## Improve Documentation
4148

4249
The easiest way to help with the `Developer Guide` and `User Guide` is to review it and provide feedback on the
43-
existing articles. Whether you notice a mistake, see the possibility of improving the text, or think more
50+
existing articles. Whether you notice a mistake, see the possibility of improving the text, or think more
4451
information should be added, you can reach out to discuss the potential changes.
4552

4653
## Report Bugs
4754

48-
If you encounter a bug, open an issue in [`Github Issues`](https://github.com/open-edge-platform/edge-ai-suites/issues). Provide the following information to help us
55+
If you encounter a bug, open an issue in [`Github Issues`](https://github.com/open-edge-platform/edge-ai-suites/issues). Provide the following information to help us
4956
understand and resolve the issue quickly:
5057

5158
- A clear and descriptive title
@@ -59,7 +66,7 @@ understand and resolve the issue quickly:
5966

6067
Intel welcomes suggestions for new features and improvements. Follow these steps to make a suggestion:
6168

62-
- Check if there's already a similar suggestion in [`Github Issues`](https://github.com/open-edge-platform/edge-ai-suites/issues).
69+
- Check if there's already a similar suggestion in [`Github Issues`](https://github.com/open-edge-platform/edge-ai-suites/issues).
6370
- If not, open a new issue and provide the following information:
6471
- A clear and descriptive title
6572
- A detailed description of the enhancement
@@ -75,7 +82,7 @@ Before submitting a pull request, ensure you follow these guidelines:
7582
- Test your changes thoroughly.
7683
- Document your changes (in code, readme, etc.).
7784
- Submit your pull request, detailing the changes and linking to any relevant issues.
78-
- Wait for a review. Intel will review your pull request as soon as possible and provide you with feedback.
85+
- Wait for a review. Intel will review your pull request as soon as possible and provide you with feedback.
7986
You can expect a merge once your changes are validated with automatic tests and approved by maintainers.
8087

8188
# Development Guidelines
@@ -95,7 +102,7 @@ Clear and informative commit messages make it easier to understand the history o
95102
- Capitalize the first letter
96103
- Keep the message concise, ideally under 50 characters
97104

98-
Please fill in the details as per the [pull request template](./.github/PULL_REQUEST_TEMPLATE.md) while submitting the
105+
Please fill in the details as per the [pull request template](./.github/PULL_REQUEST_TEMPLATE.md) while submitting the
99106
pull request.
100107

101108
## Testing

education-ai-suite/smart-classroom/components/asr_component.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,6 @@ def process(self, input_generator):
187187
if os.path.exists(chunk_path) and DELETE_CHUNK_AFTER_USE:
188188
os.remove(chunk_path)
189189

190-
StorageManager.save_async(transcript_path, transcribed_text, append=True)
191-
192190
yield {
193191
**chunk_data,
194192
"text": transcribed_text,
@@ -208,8 +206,9 @@ def process(self, input_generator):
208206
teacher_speaker = max(self.speaker_text_len, key=self.speaker_text_len.get)
209207

210208
if teacher_speaker:
211-
teacher_lines_with_time = []
209+
teacher_lines = []
212210
full_updated_lines = []
211+
full_timestamped_lines = []
213212

214213
for seg in self.all_segments:
215214
spk = seg["speaker"]
@@ -219,8 +218,8 @@ def process(self, input_generator):
219218

220219
if spk == teacher_speaker:
221220
speaker_label = LABEL_TEACHER
222-
teacher_lines_with_time.append(
223-
f"[{start} - {end}] {speaker_label}: {text}"
221+
teacher_lines.append(
222+
f"{text}"
224223
)
225224
else:
226225
if spk.startswith(f"{LABEL_SPEAKER}_"):
@@ -233,7 +232,11 @@ def process(self, input_generator):
233232
speaker_label = spk
234233

235234
full_updated_lines.append(
236-
f"[{start} - {end}] {speaker_label}: {text}"
235+
f"{speaker_label}: {text}"
236+
)
237+
238+
full_timestamped_lines.append(
239+
f"[{start} - {end}]: {text}"
237240
)
238241

239242
StorageManager.save(
@@ -242,9 +245,15 @@ def process(self, input_generator):
242245
append=False
243246
)
244247

248+
StorageManager.save(
249+
os.path.join(project_path, "content_segmentation_transcription.txt"),
250+
"\n".join(full_timestamped_lines) + "\n",
251+
append=False
252+
)
253+
245254
StorageManager.save(
246255
os.path.join(project_path, "teacher_transcription.txt"),
247-
"\n".join(teacher_lines_with_time) + "\n",
256+
"\n".join(teacher_lines) + "\n",
248257
append=False
249258
)
250259

@@ -269,4 +278,4 @@ def process(self, input_generator):
269278
}
270279
)
271280

272-
logger.info(f"Transcription Complete: {self.session_id}")
281+
logger.info(f"Transcription Complete: {self.session_id}")
Lines changed: 100 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,135 @@
11
from components.llm.base_summarizer import BaseSummarizer
2-
import logging
2+
import logging, threading, gc
33
from transformers import AutoTokenizer, TextIteratorStreamer
44
from optimum.intel.openvino import OVModelForCausalLM
55
from utils import ensure_model
66
from utils.config_loader import config
77
from utils.locks import audio_pipeline_lock
8-
import threading
98

109
logger = logging.getLogger(__name__)
1110

1211

1312
class Summarizer(BaseSummarizer):
1413
def __init__(self, model_name, device, temperature=0.7, revision=None):
1514
self.model_name = model_name
16-
self.device = device.upper() # OpenVINO uses "GPU" or "CPU"
15+
self.device = device.upper()
1716
self.temperature = temperature
1817

19-
model_path = ensure_model.get_model_path()
20-
logger.info(f"Loading Model: model name={self.model_name}, model path={model_path}, device={self.device}")
21-
18+
self.model_path = ensure_model.get_model_path()
19+
20+
logger.info(
21+
f"Summarizer initialized (lazy load). "
22+
f"model={self.model_name}, path={self.model_path}, device={self.device}"
23+
)
24+
2225
self.tokenizer = AutoTokenizer.from_pretrained(
23-
model_path,
24-
trust_remote_code=True,
25-
fix_mistral_regex=True
26+
self.model_path,
27+
trust_remote_code=True,
28+
fix_mistral_regex=True,
2629
)
2730

2831
if self.tokenizer.pad_token is None:
2932
self.tokenizer.pad_token = self.tokenizer.eos_token
30-
31-
self.model = OVModelForCausalLM.from_pretrained(
32-
model_path,
33-
device=self.device,
34-
use_cache=True
33+
34+
def _load_model(self):
35+
logger.info("Loading OVModelForCausalLM instance...")
36+
return OVModelForCausalLM.from_pretrained(
37+
self.model_path,
38+
device=self.device,
39+
use_cache=True,
3540
)
3641

42+
def _destroy_model(self, model):
43+
try:
44+
del model
45+
gc.collect()
46+
logger.info("OV model instance destroyed")
47+
except Exception as e:
48+
logger.warning(f"Failed to destroy OV model cleanly: {e}")
49+
3750
def generate(self, prompt: str, stream: bool = True):
3851
max_new_tokens = config.models.summarizer.max_new_tokens
3952
inputs = self.tokenizer(prompt, return_tensors="pt")
4053

4154
if stream:
4255
class CountingTextIteratorStreamer(TextIteratorStreamer):
43-
def __init__(self, tokenizer, skip_special_tokens=True, skip_prompt=True):
44-
super().__init__(tokenizer, skip_special_tokens=skip_special_tokens, skip_prompt=skip_prompt)
45-
self.total_tokens = 0
56+
def __init__(self, tokenizer, skip_special_tokens=True, skip_prompt=True):
57+
super().__init__(
58+
tokenizer,
59+
skip_special_tokens=skip_special_tokens,
60+
skip_prompt=skip_prompt,
61+
)
62+
self.total_tokens = 0
4663

47-
def put(self, value):
48-
if value is not None:
49-
self.total_tokens += 1
50-
super().put(value)
64+
def put(self, value):
65+
if value is not None:
66+
self.total_tokens += 1
67+
super().put(value)
5168

5269
streamer = CountingTextIteratorStreamer(
53-
self.tokenizer,
54-
skip_special_tokens=True,
55-
skip_prompt=True
70+
self.tokenizer,
71+
skip_special_tokens=True,
72+
skip_prompt=True,
5673
)
57-
74+
5875
def run_generation():
59-
with audio_pipeline_lock:
60-
generation_kwargs = {
61-
"input_ids": inputs.input_ids,
62-
"max_new_tokens": max_new_tokens,
63-
64-
# 🔑 sampling safety
65-
"do_sample": True,
66-
"temperature": max(self.temperature, 0.1),
67-
"top_p": 0.9,
68-
"top_k": 50,
69-
70-
# tokens
71-
"pad_token_id": self.tokenizer.eos_token_id,
72-
"eos_token_id": self.tokenizer.eos_token_id,
73-
74-
# streaming
75-
"streamer": streamer,
76-
}
77-
self.model.generate(**generation_kwargs)
78-
79-
thread = threading.Thread(target=run_generation, daemon=True)
80-
thread.start()
81-
76+
model = None
77+
try:
78+
with audio_pipeline_lock:
79+
model = self._load_model()
80+
model.generate(
81+
input_ids=inputs.input_ids,
82+
max_new_tokens=max_new_tokens,
83+
84+
# sampling
85+
do_sample=True,
86+
temperature=max(self.temperature, 0.1),
87+
top_p=0.9,
88+
top_k=50,
89+
90+
# tokens
91+
pad_token_id=self.tokenizer.eos_token_id,
92+
eos_token_id=self.tokenizer.eos_token_id,
93+
94+
# streaming
95+
streamer=streamer,
96+
)
97+
98+
except Exception:
99+
logger.error(
100+
"Exception occurred in OV streaming generation",
101+
exc_info=True,
102+
)
103+
if hasattr(streamer, "_queue"):
104+
streamer._queue.put(
105+
"[ERROR]: Summary generation failed due to resource constraints."
106+
)
107+
108+
finally:
109+
if model is not None:
110+
self._destroy_model(model)
111+
streamer.end()
112+
113+
threading.Thread(target=run_generation, daemon=True).start()
82114
return streamer
115+
83116
else:
84-
with audio_pipeline_lock:
85-
generation_kwargs = {
86-
"input_ids": inputs.input_ids,
87-
"max_new_tokens": max_new_tokens,
88-
89-
# 🔑 sampling safety
90-
"do_sample": True,
91-
"temperature": max(self.temperature, 0.1),
92-
"top_p": 0.9,
93-
"top_k": 50,
94-
95-
# tokens
96-
"pad_token_id": self.tokenizer.eos_token_id,
97-
"eos_token_id": self.tokenizer.eos_token_id,
98-
}
99-
return self.model.generate(**generation_kwargs)
117+
model = None
118+
try:
119+
with audio_pipeline_lock:
120+
model = self._load_model()
121+
return model.generate(
122+
input_ids=inputs.input_ids,
123+
max_new_tokens=max_new_tokens,
124+
125+
do_sample=True,
126+
temperature=max(self.temperature, 0.1),
127+
top_p=0.9,
128+
top_k=50,
129+
130+
pad_token_id=self.tokenizer.eos_token_id,
131+
eos_token_id=self.tokenizer.eos_token_id,
132+
)
133+
finally:
134+
if model is not None:
135+
self._destroy_model(model)

0 commit comments

Comments
 (0)