diff --git a/.circleci/continue_config.yml b/.circleci/continue_config.yml index c174ccfd..e725cdf5 100644 --- a/.circleci/continue_config.yml +++ b/.circleci/continue_config.yml @@ -40,6 +40,9 @@ jobs: - restore_cache: # this is the new step to restore cache keys: - macos-qt-cache-v3 + - run: + name: Install Rosetta + command: softwareupdate --install-rosetta --agree-to-license # needed for QtIFW - run: name: Installing Qt command: | @@ -325,6 +328,9 @@ jobs: - restore_cache: # this is the new step to restore cache keys: - macos-qt-cache-v3 + - run: + name: Install Rosetta + command: softwareupdate --install-rosetta --agree-to-license # needed for QtIFW - run: name: Installing Qt command: | diff --git a/.gitmodules b/.gitmodules index 4a1439e2..98c9a214 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,4 +4,4 @@ branch = master [submodule "gpt4all-chat/usearch"] path = gpt4all-chat/usearch - url = https://github.com/unum-cloud/usearch.git + url = https://github.com/nomic-ai/usearch.git diff --git a/gpt4all-backend/dlhandle.cpp b/gpt4all-backend/dlhandle.cpp index d7d46b29..e0f24ab7 100644 --- a/gpt4all-backend/dlhandle.cpp +++ b/gpt4all-backend/dlhandle.cpp @@ -46,13 +46,11 @@ Dlhandle::Dlhandle(const fs::path &fpath) // Suppress the "Entry Point Not Found" dialog, caused by outdated nvcuda.dll from the GPU driver UINT lastErrorMode = GetErrorMode(); - UINT success = SetErrorMode(lastErrorMode | SEM_FAILCRITICALERRORS); - assert(success); + SetErrorMode(lastErrorMode | SEM_FAILCRITICALERRORS); chandle = LoadLibraryExW(afpath.c_str(), NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR); - success = SetErrorMode(lastErrorMode); - assert(success); + SetErrorMode(lastErrorMode); if (!chandle) { DWORD err = GetLastError(); diff --git a/gpt4all-backend/llamamodel.cpp b/gpt4all-backend/llamamodel.cpp index a55c23bf..0e10ab8a 100644 --- a/gpt4all-backend/llamamodel.cpp +++ b/gpt4all-backend/llamamodel.cpp @@ -1003,14 +1003,14 @@ void LLamaModel::embedInternal( size_t totalTokens = 0; for (unsigned i = 0; i < inputs.size(); i++) { auto &input = inputs[i]; - for (auto it = input.begin(); it < input.end(); it += max_len) { - if (it > input.begin()) { it -= chunkOverlap; } - auto end = std::min(it + max_len, input.end()); + for (unsigned j = 0; j < input.size(); j += max_len) { + if (j) { j -= chunkOverlap; } + unsigned end = std::min(j + max_len, unsigned(input.size())); batches.push_back({ i, {} }); auto &batch = batches.back().batch; batch = prefixTokens; - batch.insert(batch.end(), it, end); - totalTokens += end - it; + batch.insert(batch.end(), input.begin() + j, input.begin() + end); + totalTokens += end - j; batch.push_back(eos_token); if (!doMean) { break; /* limit text to one chunk */ } } diff --git a/gpt4all-chat/CMakeLists.txt b/gpt4all-chat/CMakeLists.txt index 742a2e5d..81e086b4 100644 --- a/gpt4all-chat/CMakeLists.txt +++ b/gpt4all-chat/CMakeLists.txt @@ -64,14 +64,16 @@ set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) add_subdirectory(../gpt4all-backend llmodel) -set(METAL_SHADER_FILE) -if(${CMAKE_SYSTEM_NAME} MATCHES Darwin) - set(METAL_SHADER_FILE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/default.metallib) +set(CHAT_EXE_RESOURCES) + +# Metal shader library +if (APPLE) + list(APPEND CHAT_EXE_RESOURCES "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/default.metallib") endif() -set(APP_ICON_RESOURCE) +# App icon if (WIN32) - set(APP_ICON_RESOURCE "${CMAKE_CURRENT_SOURCE_DIR}/resources/gpt4all.rc") + list(APPEND CHAT_EXE_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/resources/gpt4all.rc") elseif (APPLE) # The MACOSX_BUNDLE_ICON_FILE variable is added to the Info.plist # generated by CMake. This variable contains the .icns file name, @@ -82,8 +84,24 @@ elseif (APPLE) set(APP_ICON_RESOURCE "${CMAKE_CURRENT_SOURCE_DIR}/resources/gpt4all.icns") set_source_files_properties(${APP_ICON_RESOURCE} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") + list(APPEND CHAT_EXE_RESOURCES "${APP_ICON_RESOURCE}") endif() +# Embedding model +set(LOCAL_EMBEDDING_MODEL "nomic-embed-text-v1.5.f16.gguf") +set(LOCAL_EMBEDDING_MODEL_MD5 "a5401e7f7e46ed9fcaed5b60a281d547") +set(LOCAL_EMBEDDING_MODEL_PATH "${CMAKE_BINARY_DIR}/resources/${LOCAL_EMBEDDING_MODEL}") +set(LOCAL_EMBEDDING_MODEL_URL "https://gpt4all.io/models/gguf/${LOCAL_EMBEDDING_MODEL}") +message(STATUS "Downloading embedding model from ${LOCAL_EMBEDDING_MODEL_URL} ...") +file(DOWNLOAD + "${LOCAL_EMBEDDING_MODEL_URL}" + "${LOCAL_EMBEDDING_MODEL_PATH}" + EXPECTED_HASH "MD5=${LOCAL_EMBEDDING_MODEL_MD5}" +) +message(STATUS "Embedding model downloaded to ${LOCAL_EMBEDDING_MODEL_PATH}") +if (APPLE) + list(APPEND CHAT_EXE_RESOURCES "${LOCAL_EMBEDDING_MODEL_PATH}") +endif() qt_add_executable(chat main.cpp @@ -102,9 +120,8 @@ qt_add_executable(chat server.h server.cpp logger.h logger.cpp responsetext.h responsetext.cpp - oscompat.h oscompat.cpp - ${METAL_SHADER_FILE} ${APP_ICON_RESOURCE} + ${CHAT_EXE_RESOURCES} ) qt_add_qml_module(chat @@ -197,23 +214,18 @@ qt_add_qml_module(chat ) set_target_properties(chat PROPERTIES - MACOSX_BUNDLE_GUI_IDENTIFIER gpt4all - MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} - MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} - MACOSX_BUNDLE TRUE WIN32_EXECUTABLE TRUE ) -if(${CMAKE_SYSTEM_NAME} MATCHES Darwin) +if (APPLE) set_target_properties(chat PROPERTIES + MACOSX_BUNDLE TRUE + MACOSX_BUNDLE_GUI_IDENTIFIER gpt4all + MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} + MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} + RESOURCE "${CHAT_EXE_RESOURCES}" OUTPUT_NAME gpt4all ) -endif() - -if(METAL_SHADER_FILE) - set_target_properties(chat PROPERTIES - RESOURCE ${METAL_SHADER_FILE} - ) add_dependencies(chat ggml-metal) endif() @@ -237,17 +249,6 @@ target_link_libraries(chat PRIVATE llmodel) -# -- extra resources -- - -set(LOCAL_EMBEDDING_MODEL "nomic-embed-text-v1.5.f16.gguf") -set(LOCAL_EMBEDDING_MODEL_MD5 "a5401e7f7e46ed9fcaed5b60a281d547") -file(DOWNLOAD - "https://gpt4all.io/models/gguf/${LOCAL_EMBEDDING_MODEL}" - "${CMAKE_BINARY_DIR}/resources/${LOCAL_EMBEDDING_MODEL}" - EXPECTED_HASH "MD5=${LOCAL_EMBEDDING_MODEL_MD5}" -) - - # -- install -- set(COMPONENT_NAME_MAIN ${PROJECT_NAME}) @@ -314,9 +315,11 @@ if (LLMODEL_CUDA) endif() endif() -install(FILES "${CMAKE_BINARY_DIR}/resources/${LOCAL_EMBEDDING_MODEL}" - DESTINATION resources - COMPONENT ${COMPONENT_NAME_MAIN}) +if (NOT APPLE) + install(FILES "${CMAKE_BINARY_DIR}/resources/${LOCAL_EMBEDDING_MODEL}" + DESTINATION resources + COMPONENT ${COMPONENT_NAME_MAIN}) +endif() set(CPACK_GENERATOR "IFW") set(CPACK_VERBATIM_VARIABLES YES) diff --git a/gpt4all-chat/embllm.cpp b/gpt4all-chat/embllm.cpp index d42fcec5..0b49270e 100644 --- a/gpt4all-chat/embllm.cpp +++ b/gpt4all-chat/embllm.cpp @@ -71,7 +71,13 @@ bool EmbeddingLLMWorker::loadModel() return true; } - QString filePath = u"%1/../resources/%2"_s.arg(QCoreApplication::applicationDirPath(), LOCAL_EMBEDDING_MODEL); +#ifdef Q_OS_DARWIN + static const QString embPathFmt = u"%1/../Resources/%2"_s; +#else + static const QString embPathFmt = u"%1/../resources/%2"_s; +#endif + + QString filePath = embPathFmt.arg(QCoreApplication::applicationDirPath(), LOCAL_EMBEDDING_MODEL); if (!QFileInfo::exists(filePath)) { qWarning() << "WARNING: Local embedding model not found"; return false; diff --git a/gpt4all-chat/llm.cpp b/gpt4all-chat/llm.cpp index dfbe7ca5..13820030 100644 --- a/gpt4all-chat/llm.cpp +++ b/gpt4all-chat/llm.cpp @@ -49,10 +49,10 @@ bool LLM::hasSettingsAccess() const bool LLM::checkForUpdates() const { - #ifdef GPT4ALL_OFFLINE_INSTALLER - #pragma message "offline installer build will not check for updates!" +#ifdef GPT4ALL_OFFLINE_INSTALLER +# pragma message(__FILE__ ": WARNING: offline installer build will not check for updates!") return QDesktopServices::openUrl(QUrl("https://gpt4all.io/")); - #else +#else Network::globalInstance()->trackEvent("check_for_updates"); #if defined(Q_OS_LINUX) @@ -71,7 +71,7 @@ bool LLM::checkForUpdates() const } return QProcess::startDetached(fileName); - #endif +#endif } bool LLM::directoryExists(const QString &path) diff --git a/gpt4all-chat/oscompat.cpp b/gpt4all-chat/oscompat.cpp deleted file mode 100644 index a1edc8dd..00000000 --- a/gpt4all-chat/oscompat.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "oscompat.h" - -#include -#include -#include - -#ifdef Q_OS_WIN32 -# define WIN32_LEAN_AND_MEAN -# ifndef NOMINMAX -# define NOMINMAX -# endif -# include -# include -#else -# include -# include -#endif - -bool gpt4all_fsync(int fd) -{ -#if defined(Q_OS_WIN32) - HANDLE handle = HANDLE(_get_osfhandle(fd)); - if (handle == INVALID_HANDLE_VALUE) { - errno = EBADF; - return false; - } - - if (FlushFileBuffers(handle)) - return true; - - DWORD error = GetLastError(); - switch (error) { - case ERROR_ACCESS_DENIED: // read-only file - return true; - case ERROR_INVALID_HANDLE: // not a regular file - errno = EINVAL; - default: - errno = EIO; - } - - return false; -#elif defined(Q_OS_DARWIN) - return fcntl(fd, F_FULLFSYNC, 0) == 0; -#else - return fsync(fd) == 0; -#endif -} - -bool gpt4all_fdatasync(int fd) -{ -#if defined(Q_OS_WIN32) || defined(Q_OS_DARWIN) - return gpt4all_fsync(fd); -#else - return fdatasync(fd) == 0; -#endif -} - -bool gpt4all_syncdir(const QString &path) -{ -#if defined(Q_OS_WIN32) - (void)path; // cannot sync a directory on Windows - return true; -#else - int fd = open(path.toLocal8Bit().constData(), O_RDONLY | O_DIRECTORY); - if (fd == -1) return false; - bool ok = gpt4all_fdatasync(fd); - close(fd); - return ok; -#endif -} diff --git a/gpt4all-chat/oscompat.h b/gpt4all-chat/oscompat.h deleted file mode 100644 index e4a8cfef..00000000 --- a/gpt4all-chat/oscompat.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -class QString; - -bool gpt4all_fsync(int fd); -bool gpt4all_fdatasync(int fd); -bool gpt4all_syncdir(const QString &path); diff --git a/gpt4all-chat/usearch b/gpt4all-chat/usearch index 5ea48c87..22cfa3bd 160000 --- a/gpt4all-chat/usearch +++ b/gpt4all-chat/usearch @@ -1 +1 @@ -Subproject commit 5ea48c87c56a25ab57634a8f207f80ae675ed58e +Subproject commit 22cfa3bd00ea542132ee826cdb220f9d6434bd43