요약 기능이 작동하지 않아요 :(

여러분,

이것은 셀프호스팅 인스턴스에 관한 것입니다

Discourse AI 플러그인을 활성화했는데 몇 가지 문제가 발생했습니다.
Enterprise 환경에서 작업 중이며, AI 접근은 추가 인증이 필요한 내부 엔드포인트를 통해 이루어집니다.
필요한 인증 정보를 헤더에 추가하고 요청을 OPENAI 호환 내부 엔드포인트로 전달하는 역할을 수행하는 Lambda를 갖춘 AWS API Gateway 엔드포인트를 구현했습니다.

LLM 테스트가

를 표시했고, 저는 문제가 없다고 생각했습니다.

또한 API Gateway 호출에 대한 관련 요청을 CloudWatch Logs에서도 확인할 수 있었습니다.

그런 다음 Summarization Personas(Smmmarization 및 … (약식))를 이 LLM과 연결하고 Topic Summarization을 활성화했습니다.

하지만 지금 제가 보고 있는 것은 제가 원했던 것이 아닙니다 :smiley:

그리고 이것은 변하지 않습니다 :frowning:

가장 이상한 점은, 요약 시도 요청이 CloudWatch Logs에 보이지 않는다는 것입니다.

다시 한 번 제가 한 작업을 정리하면 다음과 같습니다.

  • AI 활성화
  • 제 API Gateway 엔드포인트를 사용하여 vLLM 생성
  • 2개의 Persona(위 참조) 생성 및 제 LLM 설정과 연결
  • Summarization 활성화 및 해당 Persona 연결(둘 다 시도함)

다음에 무엇을 시도해 볼 수 있을지 모르겠습니다 :frowning:

도와주셔서 감사합니다. 인사를 전합니다.

JP

현재 테스트 엔드포인트가 다소 오해의 소지가 있어 이를 수정하고 싶습니다.

현재는 “non streaming” 엔드포인트만 테스트하고 있습니다. "streaming"은 테스트되지 않습니다.

LLM에서 스트리밍을 비활성화하면 모든 기능이 정상적으로 작동할까요? 아마도 프록시에서 스트리밍이 구현되어 있지 않은 것 같습니다.

Hey @sam,

요청을 전달하면서 LAMBDA에서 스트리밍을 비활성화(하드코딩)했습니다.

문제는 요약 API가 LAMBDA를 트리거하지 않는다는 점입니다(요청이 보이지 않아요).

LLM 테스트에서는 호출이 발생하지만, 토픽의 요약 버튼에서는 발생하지 않습니다.

아무것도 누르지 않은 것처럼요 :frowning:

감사합니다. 건배,

Julian

OpenAI 호환 엔드포인트인데 왜 제공자가 vLLM으로 설정되어 있나요?

안녕하세요,

여러 가지 엔진을 시도해 보았습니다. 죄송합니다. 스크린샷이 오해를 불러일으킬 수 있었습니다. OpenAI도 시도해 보았지만…

이것은 엔드포인트에서 받은 응답이며, 이를 그대로 Discourse 인스턴스로 전송하고 있습니다.
이렇게 하면 Discourse에서 "Internal Server Error"가 발생하는데(이번 아침까지는 테스트가 잘 작동했기 때문에 왜 그런지 확실하지 않음 :smiley: )

{
  "statusCode": 200,
  "headers": {
    "date": "Mon, 02 Jun 2025 05:57:44 GMT",
    "content-type": "application/json",
    "content-length": "1315",
    "x-content-type-options": "nosniff",
    "x-frame-options": "DENY",
    "strict-transport-security": "max-age=63072000; includeSubdomains; preload",
    "content-security-policy": "default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'",
    "referrer-policy": "no-referrer",
    "x-xss-protection": "0",
    "x-request-id": "02d33931-1e29-418e-b9a7-4eba07710e8e",
    "x-accel-buffering": "no",
    "via": "1.1 google"
  },
  "body": {
    "id": "24c1474f-bd51-4542-b87a-8608fd90b5fb",
    "choices": [
      {
        "finish_reason": "stop",
        "index": 0,
        "logprobs": null,
        "message": {
          "content": "1 + 1 equals 2.",
          "refusal": null,
          "role": "assistant",
          "annotations": [],
          "audio": null,
          "function_call": null,
          "tool_calls": null,
          "reasoning_content": null
        },
        "content_filter_results": {
          "hate": {
            "filtered": false,
            "severity": "safe"
          },
          "profanity": {
            "filtered": false,
            "detected": false
          },
          "protected_material_code": {
            "filtered": false,
            "detected": false
          },
          "protected_material_text": {
            "filtered": false,
            "detected": false
          },
          "self_harm": {
            "filtered": false,
            "severity": "safe"
          },
          "sexual": {
            "filtered": false,
            "severity": "safe"
          },
          "violence": {
            "filtered": false,
            "severity": "safe"
          }
        }
      }
    ],
    "created": 1748843864,
    "model": "openai/gpt-4o",
    "object": "chat.completion",
    "usage": {
      "prompt_tokens": 25,
      "completion_tokens": 9,
      "total_tokens": 34,
      "prompt_tokens_details": {
        "audio_tokens": 0,
        "cached_tokens": 0
      },
      "completion_tokens_details": {
        "accepted_prediction_tokens": 0,
        "audio_tokens": 0,
        "reasoning_tokens": 0,
        "rejected_prediction_tokens": 0,
        "cached_tokens": 0
      }
    },
    "cost": {
      "interaction": {
        "prompt_tokens": 0.0000688,
        "prompt_tokens_details": {
          "standard": 0.0000688,
          "cached": 0
        },
        "completion_tokens": 0.000099,
        "completion_tokens_details": {
          "standard": 0.000099,
          "reasoning": 0,
          "cached": 0
        },
        "total": 0.0001678,
        "currency": "USD"
      },
      "integrations": {},
      "total": 0.0001678,
      "currency": "USD"
    }
  }
}

Discourse 로그:

 Back to site
DiscourseAi::Completions::Endpoints::Vllm: status: 502 - body: {"message": "Internal server error"}
8:07 am
activesupport-7.2.2.1/lib/active_support/broadcast_logger.rb:134:in `block in error' 
activesupport-7.2.2.1/lib/active_support/broadcast_logger.rb:231:in `block in dispatch' 
activesupport-7.2.2.1/lib/active_support/broadcast_logger.rb:231:in `each' 
activesupport-7.2.2.1/lib/active_support/broadcast_logger.rb:231:in `dispatch' 
activesupport-7.2.2.1/lib/active_support/broadcast_logger.rb:134:in `error' 
/var/www/discourse/plugins/discourse-ai/lib/completions/endpoints/base.rb:160:in `block (2 levels) in perform_completion!' 
net-http-0.6.0/lib/net/http.rb:2433:in `block in transport_request' 
net-http-0.6.0/lib/net/http/response.rb:320:in `reading_body' 
net-http-0.6.0/lib/net/http.rb:2430:in `transport_request' 
net-http-0.6.0/lib/net/http.rb:2384:in `request' 
rack-mini-profiler-3.3.1/lib/patches/net_patches.rb:19:in `block in request_with_mini_profiler' 
rack-mini-profiler-3.3.1/lib/mini_profiler/profiling_methods.rb:50:in `step' 
rack-mini-profiler-3.3.1/lib/patches/net_patches.rb:18:in `request_with_mini_profiler' 
/var/www/discourse/plugins/discourse-ai/lib/completions/endpoints/base.rb:158:in `block in perform_completion!' 
net-http-0.6.0/lib/net/http.rb:1632:in `start' 
net-http-0.6.0/lib/net/http.rb:1070:in `start' 
/var/www/discourse/plugins/discourse-ai/lib/completions/endpoints/base.rb:129:in `perform_completion!' 
/var/www/discourse/plugins/discourse-ai/lib/completions/llm.rb:374:in `generate' 
/var/www/discourse/plugins/discourse-ai/lib/configuration/llm_validator.rb:36:in `run_test' 
/var/www/discourse/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' 
/var/www/discourse/app/controllers/application_controller.rb:428:in `block in with_resolved_locale' 
i18n-1.14.7/lib/i18n.rb:353:in `with_locale' 
/var/www/discourse/app/controllers/application_controller.rb:428: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:89: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' 
/var/www/discourse/lib/middleware/omniauth_bypass_middleware.rb:35:in `call' 
rack-2.2.13/lib/rack/tempfile_reaper.rb:15:in `call' 
rack-2.2.13/lib/rack/conditional_get.rb:27:in `call' 
rack-2.2.13/lib/rack/head.rb:12:in `call' 
actionpack-7.2.2.1/lib/action_dispatch/http/permissions_policy.rb:38:in `call' 
/var/www/discourse/lib/content_security_policy/middleware.rb:12:in `call' 
/var/www/discourse/lib/middleware/anonymous_cache.rb:415:in `call' 
/var/www/discourse/lib/middleware/csp_script_nonce_injector.rb:12:in `call' 
/var/www/discourse/config/initializers/008-rack-cors.rb:14:in `call' 
rack-2.2.13/lib/rack/session/abstract/id.rb:266:in `context' 
rack-2.2.13/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' 
/var/www/discourse/lib/middleware/default_headers.rb:13: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' 
/var/www/discourse/config/initializers/100-quiet_logger.rb:20:in `call' 
/var/www/discourse/config/initializers/100-silence_logger.rb:29:in `call' 
actionpack-7.2.2.1/lib/action_dispatch/middleware/request_id.rb:33:in `call' 
/var/www/discourse/lib/middleware/enforce_hostname.rb:24:in `call' 
rack-2.2.13/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.13/lib/rack/sendfile.rb:110:in `call' 
rack-mini-profiler-3.3.1/lib/mini_profiler.rb:191:in `call' 
/var/www/discourse/lib/middleware/processing_request.rb:12:in `call' 
message_bus-4.4.1/lib/message_bus/rack/middleware.rb:60:in `call' 
/var/www/discourse/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.13/lib/rack/urlmap.rb:74:in `block in call' 
rack-2.2.13/lib/rack/urlmap.rb:58:in `each' 
rack-2.2.13/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)>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/bin/unicorn:25:in `load' 
/var/www/discourse/vendor/bundle/ruby/3.3.0/bin/unicorn:25:in `<main>' 
infobacktraceenv
 Solve  Remove  Protect  Copy  Share
 Debug
 Info
  Warning
  Error
  Fatal
Search

 Clear logs

안녕하세요,

번역기와 포럼 헬퍼는 정상 작동 중이지만, 요약 버튼이 아무 동작도 하지 않습니다.

CloudWatch 로그에서 discourse에서 요청이 트리거되었다는 흔적을 전혀 찾을 수 없습니다.

요약기는 요약 페르소나(Summarize Persona)로 구성되어 있으며, 해당 페르소나는 이 토론에서 앞서 언급했던 LLM 엔드포인트를 사용하고 있습니다.

혹시 해결 방법을 아시는 분 계신가요?

감사합니다.

WS 드림

새로운 통찰:

일부 주제는 요약할 수 있고, 일부는 요약할 수 없습니다…

새로운 주제들은 요약할 수 있는 것 같습니다.
그리고 또 다른 질문입니다. 이미지가 포함된 주제가 있는데, 이미지 인식 AI가 없다면 이것이 문제가 될까요?

이것은 사용자 자체 엔드포인트에서 발생한 502 오류입니다 :stuck_out_tongue:

토픽 길이가 문제일까요?

이미지 캡션 생성이나 게시글 분류 자동화 같은 이미지 관련 작업에서는 문제가 될 것입니다.

Hey @Falco

하지만 discourse는 요청조차 시작하지도 않고, 왜 그런지(로그 등)에 대한 이유도 제공하지 않아요 :frowning:
선택지를 좁히기가 어렵네요

아니요, 그렇지 않았어요. 문제를 찾았어요 (llm 엔드포인트의 body를 JSON.stringify하지 않았던 것이 원인이었네요. 하지만 discourse가 이 502 에러의 원인에 대해 조금 더 자세히 알려주면 좋았을 텐데 :slight_smile: )

감사합니다, 건승하세요.

WS