Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified android/src/main/jniLibs/arm64-v8a/libcactus.a
Binary file not shown.
50 changes: 49 additions & 1 deletion cpp/HybridCactus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,54 @@ std::shared_ptr<Promise<std::string>> HybridCactus::transcribe(
});
}

std::shared_ptr<Promise<std::string>> HybridCactus::detectLanguage(
const std::variant<std::vector<double>, std::string> &audio,
double responseBufferSize,
const std::optional<std::string> &optionsJson) {
return Promise<std::string>::async(
[this, audio, optionsJson, responseBufferSize]() -> std::string {
std::lock_guard<std::mutex> lock(this->_modelMutex);

if (!this->_model) {
throw std::runtime_error("Cactus model is not initialized");
}

std::string responseBuffer;
responseBuffer.resize(responseBufferSize);

int result;
if (std::holds_alternative<std::string>(audio)) {
result = cactus_detect_language(
this->_model, std::get<std::string>(audio).c_str(),
responseBuffer.data(), responseBufferSize,
optionsJson ? optionsJson->c_str() : nullptr, nullptr, 0);
} else {
const auto &audioDoubles = std::get<std::vector<double>>(audio);

std::vector<uint8_t> audioBytes;
audioBytes.reserve(audioDoubles.size());

for (double d : audioDoubles) {
d = std::clamp(d, 0.0, 255.0);
audioBytes.emplace_back(static_cast<uint8_t>(d));
}

result = cactus_detect_language(
this->_model, nullptr, responseBuffer.data(), responseBufferSize,
optionsJson ? optionsJson->c_str() : nullptr, audioBytes.data(),
audioBytes.size());
}

if (result < 0) {
throw std::runtime_error("Cactus detect language failed: " +
std::string(cactus_get_last_error()));
}

responseBuffer.resize(strlen(responseBuffer.c_str()));
return responseBuffer;
});
}

std::shared_ptr<Promise<void>> HybridCactus::streamTranscribeStart(
const std::optional<std::string> &optionsJson) {
return Promise<void>::async([this, optionsJson]() -> void {
Expand Down Expand Up @@ -477,7 +525,7 @@ std::shared_ptr<Promise<void>> HybridCactus::destroy() {
std::shared_ptr<Promise<void>>
HybridCactus::setTelemetryEnvironment(const std::string &cacheDir) {
return Promise<void>::async([cacheDir]() -> void {
cactus_set_telemetry_environment("react-native-v1.7", cacheDir.c_str());
cactus_set_telemetry_environment("react-native", cacheDir.c_str(), "1.10.0");
});
}

Expand Down
5 changes: 5 additions & 0 deletions cpp/HybridCactus.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ class HybridCactus : public HybridCactusSpec {
double /* tokenId */)>> &callback)
override;

std::shared_ptr<Promise<std::string>>
detectLanguage(const std::variant<std::vector<double>, std::string> &audio,
double responseBufferSize,
const std::optional<std::string> &optionsJson) override;

std::shared_ptr<Promise<void>>
streamTranscribeStart(const std::optional<std::string> &optionsJson) override;

Expand Down
15 changes: 14 additions & 1 deletion cpp/cactus_ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ CACTUS_FFI_EXPORT int cactus_transcribe(
size_t pcm_buffer_size
);

CACTUS_FFI_EXPORT int cactus_detect_language(
cactus_model_t model,
const char* audio_file_path, // NULL if using pcm_buffer
char* response_buffer,
size_t buffer_size,
const char* options_json, // optional
const uint8_t* pcm_buffer, // NULL if using audio_file_path
size_t pcm_buffer_size
);

CACTUS_FFI_EXPORT cactus_stream_transcribe_t cactus_stream_transcribe_start(
cactus_model_t model,
const char* options_json // optional
Expand Down Expand Up @@ -189,7 +199,10 @@ CACTUS_FFI_EXPORT void cactus_index_destroy(cactus_index_t index);

CACTUS_FFI_EXPORT const char* cactus_get_last_error(void);

CACTUS_FFI_EXPORT void cactus_set_telemetry_environment(const char* framework, const char* cache_location);
CACTUS_FFI_EXPORT void cactus_set_telemetry_environment(const char* framework, const char* cache_location, const char* version);
CACTUS_FFI_EXPORT void cactus_set_app_id(const char* app_id);
CACTUS_FFI_EXPORT void cactus_telemetry_flush(void);
CACTUS_FFI_EXPORT void cactus_telemetry_shutdown(void);

#ifdef __cplusplus
}
Expand Down
4 changes: 2 additions & 2 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
PODS:
- boost (1.84.0)
- Cactus (1.7.0):
- Cactus (1.10.0):
- boost
- DoubleConversion
- fast_float
Expand Down Expand Up @@ -2643,7 +2643,7 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90
Cactus: d549ac2651ab939a9b5bbcfd6827a1a4e7fa2d81
Cactus: 88585f8a152312dcb391526d839133d72d054031
DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb
fast_float: b32c788ed9c6a8c584d114d0047beda9664e7cc6
FBLazyVector: b8f1312d48447cca7b4abc21ed155db14742bd03
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#ifndef CACTUS_CLOUD_H
#define CACTUS_CLOUD_H

#include "cactus_utils.h"
#include <string>
#include <vector>

namespace cactus {
namespace ffi {

struct CloudResponse {
std::string transcript;
std::string api_key_hash;
bool used_cloud = false;
std::string error;
};

struct CloudCompletionRequest {
std::vector<cactus::engine::ChatMessage> messages;
std::vector<ToolFunction> tools;
std::string local_output;
std::vector<std::string> local_function_calls;
bool has_images = false;
std::string cloud_key;
};

struct CloudCompletionResult {
bool ok = false;
bool used_cloud = false;
std::string response;
std::vector<std::string> function_calls;
std::string error;
};

std::string cloud_base64_encode(const uint8_t* data, size_t len);
std::vector<uint8_t> cloud_build_wav(const uint8_t* pcm, size_t pcm_bytes);
std::string resolve_cloud_api_key(const char* cloud_key_param);
CloudResponse cloud_transcribe_request(const std::string& audio_b64,
const std::string& fallback_text,
long timeout_seconds = 15L,
const char* cloud_key = nullptr);
CloudCompletionResult cloud_complete_request(const CloudCompletionRequest& request,
long timeout_ms);

} // namespace ffi
} // namespace cactus

#endif // CACTUS_CLOUD_H
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ CACTUS_FFI_EXPORT int cactus_transcribe(
size_t pcm_buffer_size
);

CACTUS_FFI_EXPORT int cactus_detect_language(
cactus_model_t model,
const char* audio_file_path, // NULL if using pcm_buffer
char* response_buffer,
size_t buffer_size,
const char* options_json, // optional
const uint8_t* pcm_buffer, // NULL if using audio_file_path
size_t pcm_buffer_size
);

CACTUS_FFI_EXPORT cactus_stream_transcribe_t cactus_stream_transcribe_start(
cactus_model_t model,
const char* options_json // optional
Expand Down Expand Up @@ -189,7 +199,10 @@ CACTUS_FFI_EXPORT void cactus_index_destroy(cactus_index_t index);

CACTUS_FFI_EXPORT const char* cactus_get_last_error(void);

CACTUS_FFI_EXPORT void cactus_set_telemetry_environment(const char* framework, const char* cache_location);
CACTUS_FFI_EXPORT void cactus_set_telemetry_environment(const char* framework, const char* cache_location, const char* version);
CACTUS_FFI_EXPORT void cactus_set_app_id(const char* app_id);
CACTUS_FFI_EXPORT void cactus_telemetry_flush(void);
CACTUS_FFI_EXPORT void cactus_telemetry_shutdown(void);

#ifdef __cplusplus
}
Expand Down
Loading
Loading