Compare commits

..

24 Commits

Author SHA1 Message Date
Jared Van Bortel
da32383ccb revert #include fix for now
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 19:29:52 -05:00
Jared Van Bortel
4fe97d61a9 ignore the last two warnings
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 19:29:52 -05:00
Jared Van Bortel
1f3e4d0950 ignore new warnings
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 19:12:09 -05:00
Jared Van Bortel
e6a324ebca update clang for __cpp_concepts=202002 required by libstdc++13 <expected>
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 18:51:08 -05:00
Jared Van Bortel
5c25b49bf0 explicitly install/update git and make
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 18:40:34 -05:00
Jared Van Bortel
80e831da6f further attempts to fix warnings
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 17:15:16 -05:00
Jared Van Bortel
e7ee341e28 try to fix remaining annotations
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 16:14:31 -05:00
Jared Van Bortel
f1025be542 cpp-linter: ignore third-party dependencies from FetchContent
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 15:54:16 -05:00
Jared Van Bortel
910e79f927 test with files-changed-only=false
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 15:54:16 -05:00
Jared Van Bortel
ea55810705 add libgl-dev
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 15:54:16 -05:00
Jared Van Bortel
91d6e03754 add CMAKE_PREFIX_PATH
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 15:54:16 -05:00
Jared Van Bortel
274f5fab25 fix sed path
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 15:54:16 -05:00
Jared Van Bortel
9db02ac810 fix qt packages
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 15:54:16 -05:00
Jared Van Bortel
d902c87b2a more deps
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 15:54:16 -05:00
Jared Van Bortel
bab871c278 add dep
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 15:54:16 -05:00
Jared Van Bortel
db0a823dd2 fix name
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 15:54:16 -05:00
Jared Van Bortel
48587d987b fix syntax
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 15:54:16 -05:00
Jared Van Bortel
b5eaa25f9c add self to path filter
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 15:54:16 -05:00
Jared Van Bortel
fc268acd6a ci: add GitHub action for clang-tidy
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 15:54:16 -05:00
Jared Van Bortel
8bf55e99f1 chat: cut v3.5.0-rc2 release candidate (#3229)
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 15:28:03 -05:00
Jared Van Bortel
9e306114d1 qml: tweaks to new edit/redo buttons (#3228)
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 14:14:36 -05:00
AT
2b1668eff2 Animate the removal of chat items when editing prompts. (#3227)
Signed-off-by: Adam Treat <treat.adam@gmail.com>
2024-12-06 12:26:22 -05:00
Jared Van Bortel
6b18abb124 changelog: add more changes from #3147 (#3226)
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 11:22:50 -05:00
Jared Van Bortel
f9863b3b89 add changelog entries for Jinja PR (#3223)
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
2024-12-06 11:00:29 -05:00
13 changed files with 270 additions and 130 deletions

126
.clang-tidy Normal file
View File

@@ -0,0 +1,126 @@
# vim: set ft=yaml:
HeaderFilterRegex: '/gpt4all-(backend|chat)/(src|include)/'
Checks:
- 'bugprone-*'
- 'cert-*'
- 'clang-analyzer-*'
- 'cppcoreguidelines-*'
- 'google-*'
- 'misc-*'
- 'modernize-*'
- 'performance-*'
- 'portability-*'
- 'readability-*'
- '-*-avoid-c-arrays'
- '-*-macro-to-enum'
- '-*-magic-numbers'
- '-*-narrowing-conversions'
- '-*-non-private-member-variables-in-classes'
- '-*-use-default-member-init'
- '-*readability-braces-around-statements'
- '-bugprone-assignment-in-if-condition'
- '-bugprone-branch-clone'
- '-bugprone-crtp-constructor-accessibility'
- '-bugprone-easily-swappable-parameters'
- '-bugprone-implicit-widening-of-multiplication-result'
- '-bugprone-inc-dec-in-conditions'
- '-bugprone-suspicious-string-compare'
- '-bugprone-suspicious-stringview-data-usage'
- '-bugprone-switch-missing-default-case'
- '-cert-dcl03-c'
- '-cert-err33-c'
- '-cert-err58-cpp'
- '-clang-analyzer-core.CallAndMessage'
- '-clang-analyzer-cplusplus.Move'
- '-clang-analyzer-deadcode.DeadStores'
- '-clang-analyzer-optin.performance.Padding'
- '-clang-diagnostic-missing-include-dirs'
- '-clang-diagnostic-unreachable-code-break'
- '-cppcoreguidelines-avoid-do-while'
- '-cppcoreguidelines-avoid-goto'
- '-cppcoreguidelines-avoid-non-const-global-variables'
- '-cppcoreguidelines-explicit-virtual-functions'
- '-cppcoreguidelines-init-variables'
- '-cppcoreguidelines-macro-usage'
- '-cppcoreguidelines-no-malloc'
- '-cppcoreguidelines-noexcept-move-operations'
- '-cppcoreguidelines-owning-memory'
- '-cppcoreguidelines-prefer-member-initializer'
- '-cppcoreguidelines-pro-bounds-array-to-pointer-decay'
- '-cppcoreguidelines-pro-bounds-pointer-arithmetic'
- '-cppcoreguidelines-pro-type-const-cast'
- '-cppcoreguidelines-pro-type-cstyle-cast'
- '-cppcoreguidelines-pro-type-member-init'
- '-cppcoreguidelines-pro-type-reinterpret-cast'
- '-cppcoreguidelines-pro-type-static-cast-downcast'
- '-cppcoreguidelines-pro-type-union-access'
- '-cppcoreguidelines-pro-type-vararg'
- '-cppcoreguidelines-rvalue-reference-param-not-moved'
- '-cppcoreguidelines-special-member-functions'
- '-cppcoreguidelines-virtual-class-destructor'
- '-google-build-using-namespace'
- '-google-default-arguments'
- '-google-explicit-constructor'
- '-google-global-names-in-headers'
- '-google-readability-casting'
- '-google-readability-namespace-comments'
- '-google-readability-todo'
- '-google-runtime-int'
- '-misc-const-correctness'
- '-misc-include-cleaner'
- '-misc-no-recursion'
- '-misc-static-assert'
- '-misc-unused-parameters'
- '-misc-use-anonymous-namespace'
- '-misc-use-internal-linkage'
- '-modernize-avoid-bind'
- '-modernize-deprecated-headers'
- '-modernize-loop-convert'
- '-modernize-pass-by-value'
- '-modernize-raw-string-literal'
- '-modernize-return-braced-init-list'
- '-modernize-use-auto'
- '-modernize-use-designated-initializers'
- '-modernize-use-equals-default'
- '-modernize-use-nodiscard'
- '-modernize-use-override'
- '-modernize-use-ranges'
- '-modernize-use-std-print'
- '-modernize-use-trailing-return-type'
- '-modernize-use-using'
- '-performance-avoid-endl'
- '-performance-enum-size'
- '-performance-faster-string-find'
- '-performance-for-range-copy'
- '-performance-implicit-conversion-in-loop'
- '-performance-move-const-arg'
- '-performance-noexcept-move-constructor'
- '-performance-no-automatic-move'
- '-performance-unnecessary-copy-initialization'
- '-performance-unnecessary-value-param'
- '-readability-avoid-const-params-in-decls'
- '-readability-avoid-nested-conditional-operator'
- '-readability-avoid-return-with-void-value'
- '-readability-avoid-unconditional-preprocessor-if'
- '-readability-const-return-type'
- '-readability-container-size-empty'
- '-readability-convert-member-functions-to-static'
- '-readability-else-after-return'
- '-readability-function-cognitive-complexity'
- '-readability-identifier-length'
- '-readability-implicit-bool-conversion'
- '-readability-inconsistent-declaration-parameter-name'
- '-readability-isolate-declaration'
- '-readability-math-missing-parentheses'
- '-readability-named-parameter'
- '-readability-non-const-parameter'
- '-readability-qualified-auto'
- '-readability-redundant-access-specifiers'
- '-readability-redundant-inline-specifier'
- '-readability-redundant-member-init'
- '-readability-redundant-string-init'
- '-readability-simplify-boolean-expr'
- '-readability-static-accessed-through-instance'
- '-readability-suspicious-call-argument'
- '-readability-uppercase-literal-suffix'
- '-readability-use-anyofallof'

62
.github/workflows/cpp-linter.yml vendored Normal file
View File

@@ -0,0 +1,62 @@
name: cpp-linter
on:
pull_request:
paths: ['.github/workflows/cpp-linter.yml', '**.c', '**.cpp', '**.h', '**.inl', '**CMakeLists.txt', '**.cmake']
push:
branches: [main]
paths: ['.github/workflows/cpp-linter.yml', '**.c', '**.cpp', '**.h', '**.inl', '**CMakeLists.txt', '**.cmake']
jobs:
cpp-linter:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: 'recursive'
- name: Install dependencies
run: |
wget -qO- 'https://apt.llvm.org/llvm-snapshot.gpg.key' | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc >/dev/null
sudo add-apt-repository -y 'deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main'
packages=(
clang-19 clang-format-19 clang-tidy-19 cmake git libgl-dev libopengl-dev libx11-6 libx11-xcb1 libxcb-glx0
libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-render0 libxcb-shape0
libxcb-shm0 libxcb-sync1 libxcb-xfixes0 libxcb-xinput0 libxcb-xkb1 libxcb1 libxkbcommon-dev
libxkbcommon-x11-0 libxkbcommon0 make
)
sudo apt-get update
sudo apt-get install -y "${packages[@]}" --no-install-recommends
- name: Install Qt
env:
QT_EMAIL: ${{ secrets.QT_EMAIL }}
QT_PASSWORD: ${{ secrets.QT_PASSWORD }}
run: |
wget 'https://qt.mirror.constant.com/archive/online_installers/4.8/qt-online-installer-linux-x64-4.8.0.run'
chmod +x qt-online-installer-linux-x64-4.8.0.run
./qt-online-installer-linux-x64-4.8.0.run --no-force-installations --no-default-installations \
--no-size-checking --default-answer --accept-licenses --confirm-command --accept-obligations \
--email "$QT_EMAIL" --password "$QT_PASSWORD" install \
qt.qt6.680.linux_gcc_64 extensions.qtpdf.680.linux_gcc_64 qt.qt6.680.addons.qthttpserver
- name: Configure
run: |
sed -i '/file(DOWNLOAD/,+4 s/^/#/' gpt4all-chat/CMakeLists.txt
cmake -S gpt4all-chat -B gpt4all-chat/build \
-DCMAKE_PREFIX_PATH=~/Qt/6.8.0/gcc_64/lib/cmake \
-DCMAKE_C_COMPILER=clang-19 \
-DCMAKE_CXX_COMPILER=clang++-19 \
-DLLMODEL_CUDA=OFF \
-DLLMODEL_KOMPUTE=OFF
- uses: cpp-linter/cpp-linter-action@v2
id: linter
with:
style: '' # no clang-format
extensions: 'c,cpp'
tidy-checks: '' # use .clang-tidy config
database: gpt4all-chat/build
version: 19
files-changed-only: false
ignore: 'gpt4all-chat/build/_deps|gpt4all-bindings'
- name: Fail Fast
if: steps.linter.outputs.clang-tidy-checks-failed > 0
run: exit 1

View File

@@ -312,8 +312,6 @@ int32_t llmodel_count_prompt_tokens(llmodel_model model, const char *prompt, con
void llmodel_model_foreach_special_token(llmodel_model model, llmodel_special_token_callback callback);
const char *llmodel_model_chat_template(const char *model_path, const char **error);
#ifdef __cplusplus
}
#endif

View File

@@ -34,11 +34,11 @@ llmodel_model llmodel_model_create(const char *model_path)
return fres;
}
static void llmodel_set_error(const char **errptr, std::string message)
static void llmodel_set_error(const char **errptr, const char *message)
{
thread_local static std::string last_error_message;
if (errptr) {
last_error_message = std::move(message);
last_error_message = message;
*errptr = last_error_message.c_str();
}
}
@@ -318,15 +318,3 @@ void llmodel_model_foreach_special_token(llmodel_model model, llmodel_special_to
for (auto &[name, token] : wrapper->llModel->specialTokens())
callback(name.c_str(), token.c_str());
}
const char *llmodel_model_chat_template(const char *model_path, const char **error)
{
static std::string s_chatTemplate;
auto res = LLModel::Implementation::chatTemplate(model_path);
if (res) {
s_chatTemplate = *res;
return s_chatTemplate.c_str();
}
llmodel_set_error(error, std::move(res.error()));
return nullptr;
}

View File

@@ -9,11 +9,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
### Added
- Warn on Windows if the Microsoft Visual C++ runtime libraries are not found ([#2920](https://github.com/nomic-ai/gpt4all/pull/2920))
- Basic cache for faster prefill when the input shares a prefix with previous context ([#3073](https://github.com/nomic-ai/gpt4all/pull/3073))
- Add ability to modify or replace the history of an active chat session ([#3147](https://github.com/nomic-ai/gpt4all/pull/3147))
### Changed
- Rebase llama.cpp on latest upstream as of September 26th ([#2998](https://github.com/nomic-ai/gpt4all/pull/2998))
- Change the error message when a message is too long ([#3004](https://github.com/nomic-ai/gpt4all/pull/3004))
- Fix CalledProcessError on Intel Macs since v2.8.0 ([#3045](https://github.com/nomic-ai/gpt4all/pull/3045))
- Use Jinja for chat templates instead of per-message QString.arg-style templates ([#3147](https://github.com/nomic-ai/gpt4all/pull/3147))
## [2.8.2] - 2024-08-14

View File

@@ -9,7 +9,7 @@ import textwrap
import threading
from enum import Enum
from queue import Queue
from typing import TYPE_CHECKING, Any, Callable, Generic, Iterator, Literal, NoReturn, TypeVar, overload
from typing import TYPE_CHECKING, Any, Callable, Generic, Iterable, Iterator, Literal, NoReturn, TypeVar, overload
if sys.version_info >= (3, 9):
import importlib.resources as importlib_resources
@@ -227,9 +227,6 @@ llmodel.llmodel_count_prompt_tokens.restype = ctypes.c_int32
llmodel.llmodel_model_foreach_special_token.argtypes = [ctypes.c_void_p, SpecialTokenCallback]
llmodel.llmodel_model_foreach_special_token.restype = None
llmodel.llmodel_model_chat_template.argtypes = [ctypes.c_char_p, ctypes.POINTER(ctypes.c_char_p)]
llmodel.llmodel_model_chat_template.restype = ctypes.c_char_p
ResponseCallbackType = Callable[[int, str], bool]
RawResponseCallbackType = Callable[[int, bytes], bool]
EmbCancelCallbackType: TypeAlias = 'Callable[[list[int], str], bool]'
@@ -293,7 +290,10 @@ class LLModel:
raise RuntimeError(f"Unable to instantiate model: {errmsg}")
self.model: ctypes.c_void_p | None = model
self._special_tokens_map: dict[str, str] | None = None
self.special_tokens_map: dict[str, str] = {}
llmodel.llmodel_model_foreach_special_token(
self.model, lambda n, t: self.special_tokens_map.__setitem__(n.decode(), t.decode()),
)
def __del__(self, llmodel=llmodel):
if hasattr(self, 'model'):
@@ -320,26 +320,6 @@ class LLModel:
dev = llmodel.llmodel_model_gpu_device_name(self.model)
return None if dev is None else dev.decode()
@property
def builtin_chat_template(self) -> str:
err = ctypes.c_char_p()
tmpl = llmodel.llmodel_model_chat_template(self.model_path, ctypes.byref(err))
if tmpl is not None:
return tmpl.decode()
s = err.value
raise ValueError('Failed to get chat template', 'null' if s is None else s.decode())
@property
def special_tokens_map(self) -> dict[str, str]:
if self.model is None:
self._raise_closed()
if self._special_tokens_map is None:
tokens: dict[str, str] = {}
cb = SpecialTokenCallback(lambda n, t: tokens.__setitem__(n.decode(), t.decode()))
llmodel.llmodel_model_foreach_special_token(self.model, cb)
self._special_tokens_map = tokens
return self._special_tokens_map
def count_prompt_tokens(self, prompt: str) -> int:
if self.model is None:
self._raise_closed()
@@ -351,6 +331,8 @@ class LLModel:
raise RuntimeError(f'Unable to count prompt tokens: {errmsg}')
return n_tok
llmodel.llmodel_count_prompt_tokens.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
@staticmethod
def list_gpus(mem_required: int = 0) -> list[str]:
"""

View File

@@ -37,9 +37,9 @@ DEFAULT_MODEL_DIRECTORY = Path.home() / ".cache" / "gpt4all"
ConfigType: TypeAlias = "dict[str, Any]"
# Environment setup adapted from HF transformers
@_operator_call
def _jinja_env() -> ImmutableSandboxedEnvironment:
# Environment setup adapted from HF transformers
def raise_exception(message: str) -> NoReturn:
raise jinja2.exceptions.TemplateError(message)
@@ -56,17 +56,14 @@ def _jinja_env() -> ImmutableSandboxedEnvironment:
return env
class Message(TypedDict):
"""A message in a chat with a GPT4All model."""
class MessageType(TypedDict):
role: str
content: str
class _ChatSession(NamedTuple):
template: jinja2.Template
template_source: str
history: list[Message]
class ChatSession(NamedTuple):
template: jinja2.Template
history: list[MessageType]
class Embed4All:
@@ -196,17 +193,6 @@ class GPT4All:
Python class that handles instantiation, downloading, generation and chat with GPT4All models.
"""
RE_LEGACY_SYSPROMPT = re.compile(
r"(?:^|\s)(?:### *System\b|S(?:ystem|YSTEM):)|"
r"<\|(?:im_(?:start|end)|(?:start|end)_header_id|eot_id|SYSTEM_TOKEN)\|>|<<SYS>>",
re.MULTILINE,
)
RE_JINJA_LIKE = re.compile(
r"\{%.*%\}.*\{\{.*\}\}.*\{%.*%\}",
re.DOTALL,
)
def __init__(
self,
model_name: str,
@@ -247,7 +233,7 @@ class GPT4All:
"""
self.model_type = model_type
self._chat_session: _ChatSession | None = None
self._chat_session: ChatSession | None = None
device_init = None
if sys.platform == "darwin":
@@ -274,7 +260,6 @@ class GPT4All:
# Retrieve model and download if allowed
self.config: ConfigType = self.retrieve_model(model_name, model_path=model_path, allow_download=allow_download, verbose=verbose)
self._was_allow_download = allow_download
self.model = LLModel(self.config["path"], n_ctx, ngl, backend)
if device_init is not None:
self.model.init_gpu(device_init)
@@ -306,20 +291,15 @@ class GPT4All:
return self.model.device
@property
def current_chat_session(self) -> list[Message] | None:
"""The message history of the current chat session."""
def current_chat_session(self) -> list[MessageType] | None:
return None if self._chat_session is None else self._chat_session.history
@current_chat_session.setter
def current_chat_session(self, history: list[Message]) -> None:
def current_chat_session(self, history: list[MessageType]) -> None:
if self._chat_session is None:
raise ValueError("current_chat_session may only be set when there is an active chat session")
self._chat_session.history[:] = history
@property
def current_chat_template(self) -> str | None:
return None if self._chat_session is None else self._chat_session.template_source
@staticmethod
def list_models() -> list[ConfigType]:
"""
@@ -589,13 +569,13 @@ class GPT4All:
last_msg_rendered = prompt
if self._chat_session is not None:
session = self._chat_session
def render(messages: list[Message]) -> str:
def render(messages: list[MessageType]) -> str:
return session.template.render(
messages=messages,
add_generation_prompt=True,
**self.model.special_tokens_map,
)
session.history.append(Message(role="user", content=prompt))
session.history.append(MessageType(role="user", content=prompt))
prompt = render(session.history)
if len(session.history) > 1:
last_msg_rendered = render(session.history[-1:])
@@ -610,73 +590,46 @@ class GPT4All:
def stream() -> Iterator[str]:
yield from self.model.prompt_model_streaming(prompt, _callback_wrapper, **generate_kwargs)
if self._chat_session is not None:
self._chat_session.history.append(Message(role="assistant", content=full_response))
self._chat_session.history.append(MessageType(role="assistant", content=full_response))
return stream()
self.model.prompt_model(prompt, _callback_wrapper, **generate_kwargs)
if self._chat_session is not None:
self._chat_session.history.append(Message(role="assistant", content=full_response))
self._chat_session.history.append(MessageType(role="assistant", content=full_response))
return full_response
@contextmanager
def chat_session(
self,
*,
system_message: str | Literal[False] | None = None,
chat_template: str | None = None,
warn_legacy: bool = True,
):
"""
Context manager to hold an inference optimized chat session with a GPT4All model.
Args:
system_message: An initial instruction for the model, None to use the model default, or False to disable.
Defaults to None.
system_message: An initial instruction for the model, None to use the model default, or False to disable. Defaults to None.
chat_template: Jinja template for the conversation, or None to use the model default. Defaults to None.
warn_legacy: Whether to warn about legacy system prompts or prompt templates. Defaults to True.
Raises:
ValueError: If no valid chat template was found.
"""
if system_message is None:
system_message = self.config.get("systemMessage", False)
elif system_message is not False and warn_legacy and (m := self.RE_LEGACY_SYSPROMPT.search(system_message)):
print(
"Warning: chat_session() was passed a system message that is not plain text. System messages "
f"containing {m.group()!r} or with any special prefix/suffix are no longer supported.\nTo disable this "
"warning, pass warn_legacy=False.",
file=sys.stderr,
)
if chat_template is None:
if "chatTemplate" in self.config:
if (tmpl := self.config["chatTemplate"]) is None:
raise ValueError(f"The model {self.config['name']!r} does not support chat.")
chat_template = tmpl
else:
try:
chat_template = self.model.builtin_chat_template
except ValueError as e:
if len(e.args) >= 2 and isinstance(err := e.args[1], str):
msg = (f"Failed to load default chat template from model: {err}\n"
"Please pass a template to chat_session() directly.")
if not self._was_allow_download:
msg += " If this is a built-in model, consider setting allow_download to True."
raise ValueError(msg) from None
raise
elif warn_legacy and self._is_legacy_chat_template(chat_template):
print(
"Warning: chat_session() was passed a chat template that is not in Jinja format. Old-style prompt "
"templates are no longer supported.\nTo disable this warning, pass warn_legacy=False.",
file=sys.stderr,
)
if "name" not in self.config:
raise ValueError("For sideloaded models or with allow_download=False, you must specify a chat template.")
if "chatTemplate" not in self.config:
raise NotImplementedError("This model appears to have a built-in chat template, but loading it is not "
"currently implemented. Please pass a template to chat_session() directly.")
if (tmpl := self.config["chatTemplate"]) is None:
raise ValueError(f"The model {self.config['name']!r} does not support chat.")
chat_template = tmpl
history = []
if system_message is not False:
history.append(Message(role="system", content=system_message))
self._chat_session = _ChatSession(
history.append(MessageType(role="system", content=system_message))
self._chat_session = ChatSession(
template=_jinja_env.from_string(chat_template),
template_source=chat_template,
history=history,
)
try:
@@ -694,12 +647,6 @@ class GPT4All:
"""
return LLModel.list_gpus()
@classmethod
def _is_legacy_chat_template(cls, tmpl: str) -> bool:
# check if tmpl does not look like a Jinja template
return bool(re.search(r"%[12]\b", tmpl) or not cls.RE_JINJA_LIKE.search(tmpl)
or not re.search(r"\bcontent\b", tmpl))
def append_extension_if_missing(model_name):
if not model_name.endswith((".bin", ".gguf")):

View File

@@ -68,7 +68,7 @@ def get_long_description():
setup(
name=package_name,
version="3.0.0.dev0",
version="2.8.3.dev0",
description="Python bindings for GPT4All",
long_description=get_long_description(),
long_description_content_type="text/markdown",

View File

@@ -4,15 +4,30 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## [3.5.0-rc2] - 2024-12-06
### Changed
- Fade messages out with an animation when they are removed from the chat view ([#3227](https://github.com/nomic-ai/gpt4all/pull/3227))
- Tweak wording of edit/redo confirmation dialogs ([#3228](https://github.com/nomic-ai/gpt4all/pull/3228))
- Make edit/redo buttons disabled instead of invisible when they are temporarily unavailable ([#3228](https://github.com/nomic-ai/gpt4all/pull/3228))
## [3.5.0-rc1] - 2024-12-04
### Added
- Add ability to attach text, markdown, and rst files to chat ([#3135](https://github.com/nomic-ai/gpt4all/pull/3135))
- Add feature to minimize to system tray (by [@bgallois](https://github.com/bgallois) in ([#3109](https://github.com/nomic-ai/gpt4all/pull/3109))
- Basic cache for faster prefill when the input shares a prefix with previous context ([#3073](https://github.com/nomic-ai/gpt4all/pull/3073))
- Add ability to edit prompts and regenerate any response ([#3147](https://github.com/nomic-ai/gpt4all/pull/3147))
### Changed
- Implement Qt 6.8 compatibility ([#3121](https://github.com/nomic-ai/gpt4all/pull/3121))
- Use Jinja for chat templates instead of per-message QString.arg-style templates ([#3147](https://github.com/nomic-ai/gpt4all/pull/3147))
- API server: Use system message(s) from client instead of settings ([#3147](https://github.com/nomic-ai/gpt4all/pull/3147))
- API server: Accept messages in any order supported by the model instead of requiring user/assistant pairs ([#3147](https://github.com/nomic-ai/gpt4all/pull/3147))
- Remote models: Pass system message with "system" role instead of joining with user message ([#3147](https://github.com/nomic-ai/gpt4all/pull/3147))
### Removed
- Remove option to save binary model state to disk ([#3147](https://github.com/nomic-ai/gpt4all/pull/3147))
### Fixed
- Fix bug in GUI when localdocs encounters binary data ([#3137](https://github.com/nomic-ai/gpt4all/pull/3137))
@@ -179,6 +194,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
- Fix several Vulkan resource management issues ([#2694](https://github.com/nomic-ai/gpt4all/pull/2694))
- Fix crash/hang when some models stop generating, by showing special tokens ([#2701](https://github.com/nomic-ai/gpt4all/pull/2701))
[3.5.0-rc2]: https://github.com/nomic-ai/gpt4all/compare/v3.5.0-rc1...v3.5.0-rc2
[3.5.0-rc1]: https://github.com/nomic-ai/gpt4all/compare/v3.4.2...v3.5.0-rc1
[3.4.2]: https://github.com/nomic-ai/gpt4all/compare/v3.4.1...v3.4.2
[3.4.1]: https://github.com/nomic-ai/gpt4all/compare/v3.4.0...v3.4.1

View File

@@ -6,7 +6,7 @@ set(APP_VERSION_MAJOR 3)
set(APP_VERSION_MINOR 5)
set(APP_VERSION_PATCH 0)
set(APP_VERSION_BASE "${APP_VERSION_MAJOR}.${APP_VERSION_MINOR}.${APP_VERSION_PATCH}")
set(APP_VERSION "${APP_VERSION_BASE}-rc1")
set(APP_VERSION "${APP_VERSION_BASE}-rc2")
project(gpt4all VERSION ${APP_VERSION_BASE} LANGUAGES CXX C)

View File

@@ -529,8 +529,8 @@ GridLayout {
ConfirmationDialog {
id: editPromptDialog
dialogTitle: qsTr("Edit this prompt?")
description: qsTr("The existing response and all later messages will be permanently erased.")
dialogTitle: qsTr("Edit this message?")
description: qsTr("All following messages will be permanently erased.")
onAccepted: {
const msg = currentChat.popPrompt(index);
if (msg !== null)
@@ -541,7 +541,7 @@ GridLayout {
ConfirmationDialog {
id: redoResponseDialog
dialogTitle: qsTr("Redo this response?")
description: qsTr("The existing response and all later messages will be permanently erased.")
description: qsTr("All following messages will be permanently erased.")
onAccepted: currentChat.regenerateResponse(index)
}
@@ -556,33 +556,48 @@ GridLayout {
visible: !isCurrentResponse || !currentChat.responseInProgress
enabled: opacity > 0
opacity: hoverArea.hovered
readonly property var canModify: !currentChat.isServer && currentChat.isModelLoaded && !currentChat.responseInProgress
Behavior on opacity {
OpacityAnimator { duration: 30 }
}
ChatMessageButton {
visible: parent.canModify && model.name === "Prompt: "
readonly property var editingDisabledReason: {
if (!currentChat.isModelLoaded)
return qsTr("Cannot edit chat without a loaded model.");
if (currentChat.responseInProgress)
return qsTr("Cannot edit chat while the model is generating.");
return null;
}
visible: !currentChat.isServer && model.name === "Prompt: "
enabled: editingDisabledReason === null
Layout.maximumWidth: 24
Layout.maximumHeight: 24
Layout.alignment: Qt.AlignVCenter
Layout.fillWidth: false
name: editingDisabledReason ?? qsTr("Edit")
source: "qrc:/gpt4all/icons/edit.svg"
onClicked: {
if (inputBoxText === "")
editPromptDialog.open();
}
name: qsTr("Edit")
}
ChatMessageButton {
visible: parent.canModify && model.name === "Response: "
readonly property var editingDisabledReason: {
if (!currentChat.isModelLoaded)
return qsTr("Cannot redo response without a loaded model.");
if (currentChat.responseInProgress)
return qsTr("Cannot redo response while the model is generating.");
return null;
}
visible: !currentChat.isServer && model.name === "Response: "
enabled: editingDisabledReason === null
Layout.maximumWidth: 24
Layout.maximumHeight: 24
Layout.alignment: Qt.AlignVCenter
Layout.fillWidth: false
name: qsTr("Redo")
name: editingDisabledReason ?? qsTr("Redo")
source: "qrc:/gpt4all/icons/regenerate.svg"
onClicked: redoResponseDialog.open()
}

View File

@@ -793,7 +793,7 @@ Rectangle {
ColumnLayout {
anchors.fill: parent
visible: ModelList.selectableModels.count !== 0 && chatModel.count !== 0
visible: ModelList.selectableModels.count !== 0
ListView {
id: listView
Layout.maximumWidth: 1280
@@ -825,6 +825,10 @@ Rectangle {
}
}
remove: Transition {
OpacityAnimator { to: 0; duration: 500 }
}
function scrollToEnd() {
listView.positionViewAtEnd()
}

View File

@@ -49,7 +49,7 @@ Button {
ColorOverlay {
anchors.fill: image
source: image
color: myButton.hovered ? backgroundColorHovered : backgroundColor
color: !myButton.enabled ? theme.mutedTextColor : myButton.hovered ? backgroundColorHovered : backgroundColor
}
}
Accessible.role: Accessible.Button