Skip to content

Commit 15f6a4b

Browse files
committed
Merge branch 'master' of https://github.com/openvinotoolkit/openvino.genai into HEAD
2 parents a9f68db + 1024fb5 commit 15f6a4b

File tree

106 files changed

+4361
-871
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

106 files changed

+4361
-871
lines changed

.github/workflows/coverity.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ jobs:
128128
129129
- name: Build for coverity
130130
run: |
131-
${{ env.COV_TOOL_DIR }}/bin/cov-build --config ${{ env.COV_TOOL_DIR }}/config/coverity_config.xml --tmpdir cov_temp --dir ${BUILD_DIR}/cov-int --fs-capture-search ./openvino.genai sh build.sh
131+
${{ env.COV_TOOL_DIR }}/bin/cov-build --config ${{ env.COV_TOOL_DIR }}/config/coverity_config.xml --tmpdir cov_temp --dir ${BUILD_DIR}/cov-int sh build.sh
132132
133133
- name: Pack for analysis submission
134134
run: tar -cvf - cov-int | pigz > openvino-genai.tgz

.github/workflows/deploy_gh_pages.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
lfs: true
2828

2929
- name: Setup Node.js
30-
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
30+
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
3131
with:
3232
node-version: 20
3333

.github/workflows/linux.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ env:
2626
SCCACHE_AZURE_KEY_PREFIX: genai/ubuntu/22_04/x64
2727
HF_HOME: /mount/caches/huggingface/lin
2828
OV_CACHE: /mount/caches/huggingface/.ov_cache/lin
29-
OPENVINO_LOG_LEVEL: 5
29+
OPENVINO_LOG_LEVEL: 4
3030
GENAI_ARCHIVE_NAME: genai.tar.gz
3131
GENAI_SAMPLES_NAME: genai_samples.tar.gz
3232
ARTIFACTS_SHARE: '/mount/build-artifacts'
@@ -706,7 +706,7 @@ jobs:
706706

707707
- name: Setup Node
708708
if: ${{ matrix.test.run_condition }}
709-
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
709+
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
710710
with:
711711
node-version: 21
712712

@@ -856,7 +856,7 @@ jobs:
856856
merge-multiple: true
857857

858858
- name: Setup Node ${{ env.NODE_VERSION }}
859-
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
859+
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
860860
with:
861861
node-version: ${{ env.NODE_VERSION }}
862862

.github/workflows/mac.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ env:
2424
HF_HOME: ~/.cache/hf
2525
OV_CACHE: ~/.cache/ov_cache/194c936
2626
CLEANUP_CACHE: 1
27-
OPENVINO_LOG_LEVEL: 5
27+
OPENVINO_LOG_LEVEL: 4
2828

2929
jobs:
3030
smart_ci:
@@ -620,7 +620,7 @@ jobs:
620620

621621
- name: Setup NodeJS
622622
if: ${{ matrix.test.run_condition }}
623-
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
623+
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
624624
with:
625625
node-version: 21
626626

@@ -748,7 +748,7 @@ jobs:
748748
merge-multiple: true
749749

750750
- name: Setup Node ${{ env.NODE_VERSION }}
751-
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
751+
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
752752
with:
753753
node-version: ${{ env.NODE_VERSION }}
754754

.github/workflows/manylinux_2_28.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ env:
2626
SCCACHE_AZURE_KEY_PREFIX: genai/manylinux_2_28
2727
HF_HOME: /mount/caches/huggingface/lin
2828
OV_CACHE: /mount/caches/huggingface/.ov_cache/lin
29-
OPENVINO_LOG_LEVEL: 5
29+
OPENVINO_LOG_LEVEL: 4
3030
GENAI_ARCHIVE_NAME: genai.tar.gz
3131
GENAI_SAMPLES_NAME: genai_samples.tar.gz
3232
ARTIFACTS_SHARE: '/mount/build-artifacts'
@@ -577,7 +577,7 @@ jobs:
577577
merge-multiple: true
578578

579579
- name: Setup Node ${{ env.NODE_VERSION }}
580-
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
580+
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
581581
with:
582582
node-version: ${{ env.NODE_VERSION }}
583583

.github/workflows/windows.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ env:
2424
CCACHE_MAXSIZE: 500Mi
2525
HF_HOME: C:/mount/caches/huggingface/win
2626
OV_CACHE: C:/mount/caches/huggingface/.ov_cache/win/
27-
OPENVINO_LOG_LEVEL: 5
27+
OPENVINO_LOG_LEVEL: 2 # Windows fails with out of memory because of too verbose logging
2828
ARTIFACTS_SHARE: '/mount/build-artifacts'
2929
BASE_PRODUCT_TYPE: public_windows_vs2022
3030
GENAI_WHEELS_ARTIFACT_NAME: 'genai_wheels'
@@ -799,7 +799,7 @@ jobs:
799799

800800
- name: Setup NodeJS
801801
if: ${{ matrix.test.run_condition }}
802-
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
802+
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
803803
with:
804804
node-version: 21
805805

@@ -924,7 +924,7 @@ jobs:
924924
merge-multiple: true
925925

926926
- name: Setup Node ${{ env.NODE_VERSION }}
927-
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
927+
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
928928
with:
929929
node-version: ${{ env.NODE_VERSION }}
930930

samples/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ if(ENABLE_SAMPLES)
1010
add_subdirectory(cpp/rag)
1111
add_subdirectory(c/text_generation)
1212
add_subdirectory(c/whisper_speech_recognition)
13+
add_subdirectory(c/visual_language_chat)
1314
endif()
1415

1516
install(FILES
@@ -41,4 +42,5 @@ install(DIRECTORY
4142
install(DIRECTORY
4243
c/text_generation
4344
c/whisper_speech_recognition
45+
c/visual_language_chat
4446
DESTINATION samples/c COMPONENT cpp_samples_genai)

samples/c/text_generation/chat_sample_c.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@
1414
fprintf(stderr, "[ERROR] return status %d, line %d\n", return_status, __LINE__); \
1515
goto err; \
1616
}
17-
ov_genai_streamming_status_e print_callback(const char* str, void* args) {
17+
ov_genai_streaming_status_e print_callback(const char* str, void* args) {
1818
if (str) {
1919
// If args is not null, it needs to be cast to its actual type.
2020
fprintf(stdout, "%s", str);
2121
fflush(stdout);
22-
return OV_GENAI_STREAMMING_STATUS_RUNNING;
22+
return OV_GENAI_STREAMING_STATUS_RUNNING;
2323
} else {
2424
printf("Callback executed with NULL message!\n");
25-
return OV_GENAI_STREAMMING_STATUS_STOP;
25+
return OV_GENAI_STREAMING_STATUS_STOP;
2626
}
2727
}
2828

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Copyright (C) 2025 Intel Corporation
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
find_package(OpenVINOGenAI REQUIRED
5+
PATHS
6+
"${CMAKE_BINARY_DIR}" # Reuse the package from the build.
7+
${OpenVINO_DIR} # GenAI may be installed alogside OpenVINO.
8+
NO_CMAKE_FIND_ROOT_PATH
9+
)
10+
11+
include(FetchContent)
12+
FetchContent_Declare(
13+
stb
14+
GIT_REPOSITORY https://github.com/nothings/stb.git
15+
GIT_TAG master
16+
)
17+
FetchContent_MakeAvailable(stb)
18+
19+
add_library(stb_image INTERFACE)
20+
target_include_directories(stb_image INTERFACE ${stb_SOURCE_DIR})
21+
22+
# VLM Pipeline Sample
23+
add_executable(vlm_pipeline_c vlm_pipeline.c load_image.c)
24+
25+
# Specifies that the source file should be compiled as a C source file
26+
set_source_files_properties(vlm_pipeline.c load_image.c PROPERTIES LANGUAGE C)
27+
28+
target_include_directories(vlm_pipeline_c PRIVATE
29+
${CMAKE_SOURCE_DIR}/src/c/include
30+
${stb_SOURCE_DIR}
31+
)
32+
33+
target_link_libraries(vlm_pipeline_c PRIVATE openvino::genai::c stb_image)
34+
if(UNIX AND NOT APPLE)
35+
target_link_libraries(vlm_pipeline_c PRIVATE m)
36+
endif()
37+
38+
set_target_properties(vlm_pipeline_c PROPERTIES
39+
# Ensure out-of-box LC_RPATH on macOS with SIP
40+
INSTALL_RPATH_USE_LINK_PATH ON)
41+
42+
# Install
43+
install(TARGETS vlm_pipeline_c
44+
RUNTIME DESTINATION samples_bin/
45+
COMPONENT samples_bin
46+
EXCLUDE_FROM_ALL)
47+
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
#include "load_image.h"
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
#include <string.h>
5+
6+
#ifdef _WIN32
7+
#define strcasecmp _stricmp
8+
#else
9+
#include <strings.h>
10+
#endif
11+
12+
#ifdef _WIN32
13+
#include <io.h>
14+
#define stat _stat
15+
#else
16+
#include <sys/stat.h>
17+
#endif
18+
19+
#include "openvino/c/openvino.h"
20+
21+
#define STB_IMAGE_IMPLEMENTATION
22+
#include "stb_image.h"
23+
24+
static const char* supported_extensions[] = {
25+
".jpg", ".jpeg", ".png", ".bmp", ".tga", ".psd", ".gif", ".hdr", ".pic", ".pnm"
26+
};
27+
static const size_t num_extensions = sizeof(supported_extensions) / sizeof(supported_extensions[0]);
28+
29+
static int is_supported_image(const char* filename) {
30+
if (!filename) return 0;
31+
32+
size_t len = strlen(filename);
33+
for (size_t i = 0; i < num_extensions; i++) {
34+
size_t ext_len = strlen(supported_extensions[i]);
35+
if (len >= ext_len) {
36+
const char* ext = filename + len - ext_len;
37+
if (strcasecmp(ext, supported_extensions[i]) == 0) {
38+
return 1;
39+
}
40+
}
41+
}
42+
return 0;
43+
}
44+
45+
typedef struct {
46+
unsigned char* image_data;
47+
int channels;
48+
int height;
49+
int width;
50+
} image_allocator_t;
51+
52+
static void* image_allocate(size_t bytes, size_t alignment, void* user_data) {
53+
image_allocator_t* allocator = (image_allocator_t*)user_data;
54+
if (allocator && allocator->image_data &&
55+
allocator->channels * allocator->height * allocator->width == (int)bytes) {
56+
return allocator->image_data;
57+
}
58+
return NULL;
59+
}
60+
61+
static void image_deallocate(void* ptr, size_t bytes, size_t alignment, void* user_data) {
62+
image_allocator_t* allocator = (image_allocator_t*)user_data;
63+
if (allocator && allocator->image_data &&
64+
allocator->channels * allocator->height * allocator->width == (int)bytes) {
65+
stbi_image_free(allocator->image_data);
66+
allocator->image_data = NULL;
67+
}
68+
}
69+
70+
#define CHECK_STATUS(return_status) \
71+
if (return_status != OK) { \
72+
fprintf(stderr, "[ERROR] return status %d, line %d\n", return_status, __LINE__); \
73+
goto err; \
74+
}
75+
76+
ov_tensor_t* load_image(const char* image_path) {
77+
if (!image_path) {
78+
fprintf(stderr, "Error: image_path is NULL\n");
79+
return NULL;
80+
}
81+
82+
if (!file_exists(image_path)) {
83+
fprintf(stderr, "Error: Image file '%s' does not exist\n", image_path);
84+
return NULL;
85+
}
86+
87+
int width, height, channels;
88+
const int desired_channels = 3;
89+
90+
unsigned char* data = stbi_load(image_path, &width, &height, &channels, desired_channels);
91+
if (!data) {
92+
fprintf(stderr, "Error: Failed to load image '%s': %s\n", image_path, stbi_failure_reason());
93+
return NULL;
94+
}
95+
96+
image_allocator_t* allocator = (image_allocator_t*)malloc(sizeof(image_allocator_t));
97+
if (!allocator) {
98+
fprintf(stderr, "Error: Failed to allocate memory for allocator\n");
99+
stbi_image_free(data);
100+
return NULL;
101+
}
102+
103+
allocator->image_data = data;
104+
allocator->channels = desired_channels;
105+
allocator->height = height;
106+
allocator->width = width;
107+
108+
ov_tensor_t* tensor = NULL;
109+
ov_element_type_e input_type = U8;
110+
int64_t dims[4] = {1, height, width, desired_channels};
111+
112+
ov_shape_t input_shape = {.rank = 0, .dims = NULL};
113+
ov_shape_create(4, dims, &input_shape);
114+
115+
ov_tensor_create_from_host_ptr(
116+
input_type,
117+
input_shape, // shape: [1, H, W, C]
118+
data,
119+
&tensor
120+
);
121+
122+
free(allocator);
123+
124+
return tensor;
125+
}
126+
127+
const ov_tensor_t** load_images(const char* image_path, size_t* tensor_count) {
128+
if (!image_path || !tensor_count) {
129+
fprintf(stderr, "Error: image_path or tensor_count is NULL\n");
130+
return NULL;
131+
}
132+
133+
if (!file_exists(image_path)) {
134+
fprintf(stderr, "Error: Image file '%s' does not exist\n", image_path);
135+
return NULL;
136+
}
137+
138+
ov_tensor_t* tensor = load_image(image_path);
139+
if (!tensor) {
140+
return NULL;
141+
}
142+
143+
const ov_tensor_t** tensors = (const ov_tensor_t**)malloc(sizeof(ov_tensor_t*));
144+
if (!tensors) {
145+
fprintf(stderr, "Error: Failed to allocate memory for single tensor\n");
146+
free_tensor(tensor);
147+
return NULL;
148+
}
149+
150+
tensors[0] = tensor;
151+
*tensor_count = 1;
152+
153+
return tensors;
154+
}
155+
156+
void free_tensor(ov_tensor_t* tensor) {
157+
if (tensor) {
158+
ov_tensor_free(tensor);
159+
}
160+
}
161+
162+
void free_tensor_array(ov_tensor_t** tensors, size_t count) {
163+
if (tensors) {
164+
for (size_t i = 0; i < count; i++) {
165+
if (tensors[i]) {
166+
ov_tensor_free(tensors[i]);
167+
}
168+
}
169+
free(tensors);
170+
}
171+
}
172+
173+
int file_exists(const char* path) {
174+
if (!path) return 0;
175+
176+
struct stat buffer;
177+
return (stat(path, &buffer) == 0);
178+
}
179+

0 commit comments

Comments
 (0)