Интересно, у кого-нибудь получилось заставить это работать с Ollama локально?
Я тоже пытаюсь заставить это работать с Ollama. Похоже, что API, используемый плагином Discourse AI, несовместим с Ollama, и любые изменения настроек не влияют на формат запроса к API.
Вот команда, которая работает с Ollama:
curl http://192.168.1.2:11434/api/generate -d '{
"model": "llama3.2",
"prompt": "Why is the sky blue?"
}'
И, похоже, плагин пытается отправить только запрос такого типа, то есть:
curl http://192.168.1.2:11434/ \
-X POST \
-H 'Content-Type: application/json' \
-d '{"inputs":"<s>[INST] What is your favourite condiment? [/INST] Well, Im quite partial to a good squeeze of fresh lemon juice. It adds just the right amount of zesty flavour to whatever Im cooking up in the kitchen!</s> [INST] Do you have mayonnaise recipes? [/INST]","parameters":{"max_new_tokens":500, "temperature":0.5,"top_p": 0.9}}'
Чат-бот с поддержкой ИИ, якобы, совместим с Ollama, но мне тоже не удалось получить от него ответ.
Так что, если кто-то уже заставил это работать с Ollama, пожалуйста, поделитесь использованными настройками!
Похоже, я поспешил с выводами: если в плагине Discourse AI не заданы никакие настройки и я следую инструкциям по RAG из этого поста, то в чат-боте AI действительно получаю ответы от Ollama!
У нас всё отлично работает с Ollama, несколько человек из команды уже используют её.
Круто. Есть где-то руководство, которому мы можем следовать, чтобы реализовать это?
Меня больше интересуют суммаризация и другие функции, чем чат-бот.
ETA: Эта конфигурация не работает:
(Здесь я скрыл IP-адрес моего хоста).
Что происходит: при нажатии кнопки “Run Test” я получаю ошибку Internal Server Error.
В /logs я вижу:
NameError (undefined local variable or method `tokenizer' for an instance of DiscourseAi::Completions::Dialects::ChatGpt)
app/controllers/application_controller.rb:427:in `block in with_resolved_locale'
app/controllers/application_controller.rb:427:in `with_resolved_locale'
lib/middleware/omniauth_bypass_middleware.rb:35:in `call'
lib/content_security_policy/middleware.rb:12:in `call'
lib/middleware/anonymous_cache.rb:409:in `call'
lib/middleware/csp_script_nonce_injector.rb:12:in `call'
config/initializers/008-rack-cors.rb:14:in `call'
config/initializers/100-quiet_logger.rb:20:in `call'
config/initializers/100-silence_logger.rb:29:in `call'
lib/middleware/enforce_hostname.rb:24:in `call'
lib/middleware/processing_request.rb:12:in `call'
lib/middleware/request_tracker.rb:385:in `call'
Это происходит независимо от выбранного токенизатора. Я тестирую это на версии 3.5.0beta1-dev (c1ee4e120e).
Установите URL в http://localhost:11434/v1/chat/completions
Тест по-прежнему завершается с ошибкой внутреннего сервера, сообщение в логе также не изменилось — NameError, указывающий, что ‘tokenizer’ является неопределённой локальной переменной.
Попробуйте сохранить модель без изменений, обновить страницу, вернуться через кнопку «Редактировать LLM» и запустить новый тест.
Тот же результат — я уже пробовал несколько раз, но только что повторил.
Устанавливал обычным способом — добавил в файл app.yml и выполнил ./launcher rebuild app.
Добавленная строка:
hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- sudo -E -u discourse git clone https://github.com/discourse/discourse-ai.git
(Я удалил из списка другие плагины, но оставил компоненты YAML, чтобы вы могли видеть, где это находится в файле YAML.)
Завтра я верну свой локальный Ollama в рабочее состояние и отчитаюсь здесь.
Я выполнил:
ollama serve
ollama run phi4
# тест
curl http://localhost:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "phi4",
"messages": [
{
"role": "system",
"content": "Вы — полезный помощник."
},
{
"role": "user",
"content": "Сколько будет 1+1?"
}
]
}' -s | jq .choices[].message.content
"Сумма 1 + 1 равна 2. \n\nВ элементарной арифметике, когда вы прибавляете одну единицу к другой отдельной единице, общее количество становится равным двум единицам. Эта операция является частью фундаментальных принципов сложения, используемых в математике. Есть ли что-то ещё, с чем я могу вам помочь, касающееся математики или любой другой темы?"
Проверил это на Helper
Спасибо за тестирование.
Я заметил, что у меня есть дополнительный параметр (Отключить потоковые завершения), которого нет в вашей конфигурации. Возможно, проблема в выборе модели? (У меня установлен deepseek-r1:32b).
curl http://localhost:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-r1:32b",
"messages": [
{
"role": "system",
"content": "Вы — полезный помощник."
},
{
"role": "user",
"content": "Сколько будет 1+1?"
}
]
}' -s | jq .choices[].message.content
"<think>\nХорошо, я пытаюсь понять, сколько будет 1 плюс 1. Давайте разберём это шаг за шагом, хотя это кажется простым.\n\nВо-первых, я знаю, что сложение — это объединение двух чисел для получения общей суммы. Так что, когда мы говорим 1 + 1, мы фактически соединяем один объект с другим, чтобы узнать, сколько их всего.\n\nДавайте представим это: предположим, у меня в левой руке одно яблоко, а в правой — другое. Если я соединю их, сколько яблок у меня будет? Должно быть два, верно?\n\nДругой способ подумать об этом — использовать числовую прямую. Начиная с числа 1, если я сделаю ещё один шаг вперёд, куда я попаду? Точно, на число 2.\n\nЯ также могу использовать пальцы для счёта. Поднимите один палец на левой руке и один на правой. Теперь посчитайте их все: один, два. Таким образом, у меня получается два пальца, что означает 1 + 1 = 2.\n\nВозможно, стоит проверить, есть ли другой подход или метод. Например, в двоичной системе счисления, используемой компьютерами, 1 + 1 равно 10, потому что после достижения 2 (которое представлено как 10) происходит перенос. Но это другой контекст. В стандартной десятичной арифметике, которую мы используем ежедневно, 1 + 1 остаётся равным 2.\n\nТакже можно рассмотреть понятие множеств. Если у меня есть множество, содержащее один элемент, и другое множество с одним элементом, их объединение даст множество из двух элементов. Это подтверждает, что 1 + 1 равно 2.\n\nМожет возникнуть вопрос, есть ли ситуация, когда 1 + 1 не равно 2. Но в рамках базовой арифметики и математики, как мы её изучаем, ответ всегда два.\n\nЧтобы убедиться, что я ничего не упускаю, возможно, стоит обратиться к некоторым математическим доказательствам или принципам, подтверждающим это. Например, в аксиомах Пеано, которые лежат в основе арифметики, идея сложения 1 с 1 следует из аксиомы, согласно которой у каждого натурального числа есть следующий элемент, а 2 определяется как следующий после 1.\n\nТаким образом, объединяя все эти мысли — визуализацию объектов, использование числовой прямой, счёт пальцами, рассмотрение множеств и даже упоминание математических аксиом — всё указывает на то, что 1 + 1 равно 2.\n</think>\n\nРезультат сложения 1 и 1 равен 2. Это можно увидеть в простой арифметике и различными способами визуализации задачи.\n\n**Ответ:** \n$1 + 1 = \\boxed{2}$"
Результат похожий, но с этой конкретной моделью у меня появляются теги <think> — возможно, эта модель не подходит для данного использования.
Я только что пересобрал (то есть выполнил ./launcher rebuild app) свою установку и убедился, что всё актуально — на странице обновлений я вижу сообщение «всё обновлено».
При выборе как deepseek-r1:32b, так и phi4 (который я также установил и протестировал), в браузере всё ещё появляется ответ с внутренней ошибкой сервера.
Однако в логах я вижу что-то новое.
FinalDestination::SSRFDetector::DisallowedIpError (FinalDestination: все разрешённые IP-адреса были запрещены) lib/final_destination/ssrf_detector.rb:105:in 'lookup_and_filter_ips' lib/final_destination/http'
lib/final_destination/ssrf_detector.rb:105:in `lookup_and_filter_ips`
lib/final_destination/http.rb:15:in `connect`
net-http (0.6.0) lib/net/http.rb:1642:in `do_start`
net-http (0.6.0) lib/net/http.rb:1631:in `start`
net-http (0.6.0) lib/net/http.rb:1070:in `start`
plugins/discourse-ai/lib/completions/endpoints/base.rb:105:in `perform_completion!`
plugins/discourse-ai/lib/completions/endpoints/open_ai.rb:44:in `perform_completion!`
plugins/discourse-ai/lib/completions/llm.rb:281:in `generate`
plugins/discourse-ai/lib/configuration/llm_validator.rb:36:in `run_test`
plugins/discourse-ai/app/controllers/discourse_ai/admin/ai_llms_controller.rb:128:in `test`
actionpack (7.2.2.1) lib/action_controller/metal/basic_implicit_render.rb:8:in `send_action`
actionpack (7.2.2.1) lib/abstract_controller/base.rb:226:in `process_action`
actionpack (7.2.2.1) lib/action_controller/metal/rendering.rb:193:in `process_action`
actionpack (7.2.2.1) lib/abstract_controller/callbacks.rb:261:in `block in process_action`
activesupport (7.2.2.1) lib/active_support/callbacks.rb:121:in `block in run_callbacks`
app/controllers/application_controller.rb:427:in `block in with_resolved_locale`
i18n (1.14.7) lib/i18n.rb:353:in `with_locale`
app/controllers/application_controller.rb:427:in `with_resolved_locale`
activesupport (7.2.2.1) lib/active_support/callbacks.rb:130:in `block in run_callbacks`
activesupport (7.2.2.1) lib/active_support/callbacks.rb:141:in `run_callbacks`
actionpack (7.2.2.1) lib/abstract_controller/callbacks.rb:260:in `process_action`
actionpack (7.2.2.1) lib/action_controller/metal/rescue.rb:27:in `process_action`
actionpack (7.2.2.1) lib/action_controller/metal/instrumentation.rb:77:in `block in process_action`
activesupport (7.2.2.1) lib/active_support/notifications.rb:210:in `block in instrument`
activesupport (7.2.2.1) lib/active_support/notifications/instrumenter.rb:58:in `instrument`
activesupport (7.2.2.1) lib/active_support/notifications.rb:210:in `instrument`
actionpack (7.2.2.1) lib/action_controller/metal/instrumentation.rb:76:in `process_action`
actionpack (7.2.2.1) lib/action_controller/metal/params_wrapper.rb:259:in `process_action`
activerecord (7.2.2.1) lib/active_record/railties/controller_runtime.rb:39:in `process_action`
actionpack (7.2.2.1) lib/abstract_controller/base.rb:163:in `process`
actionview (7.2.2.1) lib/action_view/rendering.rb:40:in `process`
rack-mini-profiler (3.3.1) lib/mini_profiler/profiling_methods.rb:115:in `block in profile_method`
actionpack (7.2.2.1) lib/action_controller/metal.rb:252:in `dispatch`
actionpack (7.2.2.1) lib/action_controller/metal.rb:335:in `dispatch`
actionpack (7.2.2.1) lib/action_dispatch/routing/route_set.rb:67:in `dispatch`
actionpack (7.2.2.1) lib/action_dispatch/routing/route_set.rb:50:in `serve`
actionpack (7.2.2.1) lib/action_dispatch/routing/mapper.rb:32:in `block in <class:Constraints>`
actionpack (7.2.2.1) lib/action_dispatch/routing/mapper.rb:62:in `serve`
actionpack (7.2.2.1) lib/action_dispatch/journey/router.rb:53:in `block in serve`
actionpack (7.2.2.1) lib/action_dispatch/journey/router.rb:133:in `block in find_routes`
actionpack (7.2.2.1) lib/action_dispatch/journey/router.rb:126:in `each`
actionpack (7.2.2.1) lib/action_dispatch/journey/router.rb:126:in `find_routes`
actionpack (7.2.2.1) lib/action_dispatch/journey/router.rb:34:in `serve`
actionpack (7.2.2.1) lib/action_dispatch/routing/route_set.rb:896:in `call`
lib/middleware/omniauth_bypass_middleware.rb:35:in `call`
rack (2.2.11) lib/rack/tempfile_reaper.rb:15:in `call`
rack (2.2.11) lib/rack/conditional_get.rb:27:in `call`
rack (2.2.11) lib/rack/head.rb:12:in `call`
actionpack (7.2.2.1) lib/action_dispatch/http/permissions_policy.rb:38:in `call`
lib/content_security_policy/middleware.rb:12:in `call`
lib/middleware/anonymous_cache.rb:409:in `call`
lib/middleware/csp_script_nonce_injector.rb:12:in `call`
config/initializers/008-rack-cors.rb:14:in `call`
rack (2.2.11) lib/rack/session/abstract/id.rb:266:in `context`
rack (2.2.11) lib/rack/session/abstract/id.rb:260:in `call`
actionpack (7.2.2.1) lib/action_dispatch/middleware/cookies.rb:704:in `call`
actionpack (7.2.2.1) lib/action_dispatch/middleware/callbacks.rb:31:in `block in call`
activesupport (7.2.2.1) lib/active_support/callbacks.rb:101:in `run_callbacks`
actionpack (7.2.2.1) lib/action_dispatch/middleware/callbacks.rb:30:in `call`
actionpack (7.2.2.1) lib/action_dispatch/middleware/debug_exceptions.rb:31:in `call`
actionpack (7.2.2.1) lib/action_dispatch/middleware/show_exceptions.rb:32:in `call`
logster (2.20.1) lib/logster/middleware/reporter.rb:40:in `call`
railties (7.2.2.1) lib/rails/rack/logger.rb:41:in `call_app`
railties (7.2.2.1) lib/rails/rack/logger.rb:29:in `call`
config/initializers/100-quiet_logger.rb:20:in `call`
config/initializers/100-silence_logger.rb:29:in `call`
actionpack (7.2.2.1) lib/action_dispatch/middleware/request_id.rb:33:in `call`
lib/middleware/enforce_hostname.rb:24:in `call`
rack (2.2.11) lib/rack/method_override.rb:24:in `call`
actionpack (7.2.2.1) lib/action_dispatch/middleware/executor.rb:16:in `call`
rack (2.2.11) lib/rack/sendfile.rb:110:in `call`
rack-mini-profiler (3.3.1) lib/mini_profiler.rb:334:in `call`
lib/middleware/processing_request.rb:12:in `call`
message_bus (4.3.9) lib/message_bus/rack/middleware.rb:60:in `call`
lib/middleware/request_tracker.rb:385:in `call`
actionpack (7.2.2.1) lib/action_dispatch/middleware/remote_ip.rb:96:in `call`
railties (7.2.2.1) lib/rails/engine.rb:535:in `call`
railties (7.2.2.1) lib/rails/railtie.rb:226:in `public_send`
railties (7.2.2.1) lib/rails/railtie.rb:226:in `method_missing`
rack (2.2.11) lib/rack/urlmap.rb:74:in `block in call`
rack (2.2.11) lib/rack/urlmap.rb:58:in `each`
rack (2.2.11) lib/rack/urlmap.rb:58:in `call`
unicorn (6.1.0) lib/unicorn/http_server.rb:634:in `process_client`
unicorn (6.1.0) lib/unicorn/http_server.rb:739:in `worker_loop`
unicorn (6.1.0) lib/unicorn/http_server.rb:547:in `spawn_missing_workers`
unicorn (6.1.0) lib/unicorn/http_server.rb:143:in `start`
unicorn (6.1.0) bin/unicorn:128:in `<top (required)>`
vendor/bundle/ruby/3.3.0/bin/unicorn:25:in `load`
vendor/bundle/ruby/3.3.0/bin/unicorn:25:in `<main>`
Эта установка Discourse относительно свежая, и я не настраивал блокировку IP-адресов. Кроме того, я единственный пользователь системы. Я запускаю Ollama в контейнере Docker, но это не должно быть проблемой; я также использую Open WebUI (также из другого контейнера Docker) с этим экземпляром, и он работает нормально. Я использую локальный IP-адрес вместо «localhost», но «localhost» ведёт себя не иначе.
Очень ценю ваше время, которое вы тратите на помощь в выяснении того, что происходит здесь.
ETA: Я установил jq в контейнере Docker Discourse и выполнил команду curl (заменив localhost на свой локальный IP-адрес), и она успешно выполнилась оттуда — значит, связь между контейнерами есть, и URL указан верно).
Это срабатывает наша защита по умолчанию от SSRF. Вы можете добавить исключения через переменную окружения DISCOURSE_ALLOWED_INTERNAL_HOSTS.
Она срабатывает, когда Discourse пытается обратиться к IP-адресу, считающемуся внутренним.
Круто, сработало! Я сделал это через настройки, а не через переменную окружения, но тест теперь проходит. Ещё раз спасибо за всю помощь!


