Estou curioso para saber se alguém conseguiu fazer isso funcionar com o Ollama localmente?
Também estou tentando fazer isso funcionar com o ollama, parece que a API usada pelo plugin Discourse AI não é compatível com o Ollama e quaisquer configurações que eu altere não mudam a solicitação da API.
É isso que funciona com o ollama:
curl http://192.168.1.2:11434/api/generate -d '{"model": "llama3.2", "prompt": "Por que o céu é azul?"}'
E acima parece ser o único tipo de solicitação que o plugin está tentando. por exemplo:
curl http://192.168.1.2:11434/ \
-X POST \
-H 'Content-Type: application/json' \
-d '{"inputs":"<s>[INST] Qual é o seu condimento favorito? [/INST] Bem, sou bastante adepto de um bom esguicho de suco de limão fresco. Ele adiciona a quantidade certa de sabor cítrico a qualquer coisa que eu esteja cozinhando na cozinha!</s> [INST] Você tem receitas de maionese? [/INST]","parameters":{"max_new_tokens":500, "temperature":0.5,"top_p": 0.9}}'
O chatbot de IA supostamente suporta ollama, mas também não consigo obter uma resposta.
Então, sim, qualquer pessoa que tenha conseguido fazer isso funcionar com ollama, por favor, poste quais configurações você usou!
Aparentemente, falei cedo demais, se eu não tiver nenhuma configuração no plugin Discourse AI definida e seguir as instruções do RAG neste post, recebo respostas no chatbot de IA do Ollama!
Funciona perfeitamente com o ollama, temos várias pessoas na equipe usando-o.
Legal. Existe algum guia que possamos seguir sobre como implementá-lo?
Estou mais interessado na sumarização e em outras funções do que no chatbot.
ETA: Esta configuração não funciona:
(Eu ocultei o endereço IP do meu host aqui).
O que acontece é que recebo um Erro Interno do Servidor quando clico em “Executar Teste”.
Em /logs, vejo:
NameError (variável local ou método `tokenizer' indefinido para uma instância de 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/middleware/csp_script_nonce_injector.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'
Isso acontece independentemente do tokenizador que eu selecionar. Estou testando isso em 3.5.0beta1-dev (c1ee4e120e).
Defina a URL para http://localhost:11434/v1/chat/completions
O teste ainda falha com o erro interno do servidor, mesma mensagem de log também - um NameError dizendo que ‘tokenizer’ é uma variável local indefinida.
Tente salvar o modelo como está, atualizar a página e, em seguida, voltar pelo botão de edição do LLM e executar um novo teste.
Mesmo resultado - já passei por isso algumas vezes, mas tentei novamente.
Fiz a instalação da maneira usual - adicionei ao meu arquivo app.yml e executei ./launcher rebuild app
A linha que adicionei foi:
hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- sudo -E -u discourse git clone https://github.com/discourse/discourse-ai.git
(Removi os outros plugins da lista, mas deixei os componentes do yml para que você possa ver onde isso está no arquivo yml.)
Amanhã recuperarei minha configuração local do Ollama e reportarei aqui.
Eu fiz:
ollama serve
ollama run phi4
# test
curl http://localhost:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "phi4",
"messages": [
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": "How much is 1+1?"
}
]
}' -s | jq .choices[].message.content
"A soma de 1 + 1 é 2.
Na aritmética básica, ao adicionar uma unidade a outra unidade única, o número total se torna duas unidades. Esta operação faz parte dos princípios fundamentais de adição usados na matemática. Há algo mais em que posso ajudar em relação à matemática ou a qualquer outro tópico?"
Testei no Helper
Obrigado por testar isso.
Notei que tenho uma opção extra (Desabilitar conclusões em streaming) em comparação com sua configuração. É possível que seja a seleção do modelo que esteja causando um problema para mim? (Tenho o deepseek-r1:32b instalado).
curl http://localhost:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-r1:32b",
"messages": [
{
"role": "system",
"content": "Você é um assistente útil."
},
{
"role": "user",
"content": "Quanto é 1+1?"
}
]
}' -s | jq .choices[].message.content
"<think>\nCerto, estou tentando descobrir quanto é 1 mais 1. Ok, vamos analisar isso passo a passo, mesmo que pareça simples.\n\nPrimeiro, sei que adição é combinar dois números para obter uma soma total. Então, quando dizemos 1 + 1, estamos essencialmente juntando um objeto e outro objeto para ver quantos temos no total.\n\nDeixe-me visualizar: imagine que tenho uma maçã na mão esquerda e outra maçã na mão direita. Se eu as juntar, quantas maçãs terei? Devem ser duas maçãs, certo?\n\nOutra maneira de pensar nisso é usando uma reta numérica. Começando no número 1, se eu avançar mais um passo, onde pousarei? Isso mesmo, no número 2.\n\nPosso também usar os dedos para contar. Levanto um dedo na mão esquerda e outro na direita. Agora, conte-os todos: um, dois. Então isso me dá um total de dois dedos, o que significa que 1 + 1 = 2.\n\nTalvez eu devesse verificar se há outra perspectiva ou método. Por exemplo, no sistema binário, o sistema numérico usado por computadores, 1 + 1 é igual a 10 porque ocorre um transporte após atingir 2 (que é representado como 10). Mas isso é um contexto diferente. Na aritmética padrão em base 10, que usamos diariamente, 1 + 1 permanece 2.\n\nDeixe-me também considerar o conceito de conjuntos. Se eu tiver um conjunto contendo um elemento e outro conjunto com um elemento, combiná-los resultaria em um conjunto com dois elementos. Isso reforça que 1 + 1 é igual a 2.\n\nPosso me perguntar se há algum cenário em que 1 + 1 não seja igual a 2. Mas, dentro do domínio da aritmética básica e da matemática como a aprendemos, a resposta é consistentemente dois.\n\nPara garantir que não estou perdendo nada, talvez eu devesse investigar algumas provas ou princípios matemáticos que confirmem isso. Por exemplo, nos axiomas de Peano, que formam a base da aritmética, a ideia de somar 1 a 1 seguiria o axioma de que todo número natural tem um sucessor, e 2 é definido como o sucessor de 1.\n\nPortanto, juntando todos esses pensamentos — visualizar objetos, usar uma reta numérica, contar dedos, considerar conjuntos e até mesmo tocar em axiomas matemáticos — tudo aponta para 1 + 1 sendo igual a 2.\n</think>\n\nO resultado de somar 1 e 1 juntos é 2. Isso pode ser visto na aritmética simples e de várias formas de visualizar o problema.\n\n**Resposta:** \n$1 + 1 = \\boxed{2}$"
Resultado similar, embora eu obtenha as tags <think> com este modelo específico — então talvez o modelo não seja adequado para este uso.
Acabei de reconstruir (ou seja, ./launcher rebuild app) minha instalação e garanti que tudo estivesse atualizado — eu vejo “tudo atualizado” na minha página de Atualização.
Selecionando tanto o deepseek-r1:32b quanto o phi4 (que também instalei e testei), ainda estou recebendo a resposta de erro de servidor interno no navegador.
Mas nos meus logs, estou vendo algo novo.
FinalDestination::SSRFDetector::DisallowedIpError (FinalDestination: todos os IPs resolvidos foram proibidos) 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>'
Esta instalação do Discourse é relativamente nova e não configurei nenhum bloqueio de endereço IP. Também sou o único usuário nela. Estou executando o ollama em um contêiner Docker, mas isso não deveria ser um problema; eu uso o open-webui (também de outro contêiner Docker) com a instância e isso funciona bem. Estou usando o endereço IP local em vez de “localhost”, mas “localhost” não se comporta de forma diferente.
Agradeço o tempo que você está dedicando para ajudar a descobrir o que está acontecendo aqui.
ETA: Instalei o jq no contêiner Docker do Discourse e executei o comando curl (substituindo meu endereço IP local por localhost), e ele funcionou a partir de lá — então há conectividade entre os contêineres e a URL está correta).
Essa é a nossa proteção SSRF padrão entrando em ação. Você pode adicionar exceções a ela por meio da variável de ambiente DISCOURSE_ALLOWED_INTERNAL_HOSTS.
Ela é acionada quando o Discourse está tentando acessar um IP considerado interno.
Legal, isso resolveu - eu fiz isso pelas configurações em vez da variável de ambiente, mas o teste passou agora. Obrigado novamente por toda a ajuda!


