Discourse AI로 인해 새로운 SSL 및 Connection Reset by Peer 오류 발생

우선순위/중요도:
최근 저장소 변경 사항으로 인해 현재 OpenAI API와 함께 Discourse AI가 거의 작동하지 않습니다.

플랫폼:

  • 자체 호스팅, 표준 스탠드얼론 빌드 사용
  • Ubuntu 24.04 호스트 VM, Docker 컨테이너
  • OpenAI API
  • Anthropic API

설명:

Discourse AI는 외부 API인 OpenAI 모델을 호출하고 있으며, 2월 15일(마지막 컨테이너 재빌드)까지는 잘 작동하고 있었습니다. 오늘(2월 21일) 컨테이너를 재빌드한 후 문제가 발생했습니다.

알고 있는 내용은 다음과 같습니다:

2월 15일 기준
설정 및 정상 작동 중이던 OpenAI 모델:

  • LLM/페르소나
    • GPT4 Omni
    • GPT4 Omni Mini
  • 임베딩
    • text-embedding-ada-002

2월 21일 기준

모든 OpenAI 모델에서 LLM 호출 시 약 70~80%의 오류율이 발생하며, 오류 메시지는 "Connection Reset by Peer"입니다. 일부 채팅은 성공하지만, 일부는 중간에 실패합니다. 임베딩 호출은 Faraday::ConnectionFailed SSL 오류로 실패합니다.

추가적으로 실패하는 OpenAI 모델:

  • o1-mini와 o1-preview는 LLM 테스트/저장 시 코드 오류(‘developer’ is not a valid role)로 실패합니다. ‘developer’ 역할은 o1o3 모델에서만 유효하며, -mini 버전에서는 유효하지 않기 때문입니다. 소스 코드 github.com/discourse/discourse-ai/…/chat_gpt.rb:61starts_with 매칭이 아닌 정확한 모델 이름 매칭을 수행하도록 업데이트되어야 합니다. 73번째 줄의 else 케이스에는 더 이상 system 사용자가 없으므로, 단순히 user로 업데이트해야 합니다. 현재 o1-mini는 도구를 사용할 수 없습니다.

시도해 본 내용:

  • OpenAI 플랫폼 한도를 확인했으며, Rate Limits를 훨씬 하회하고 OpenAI 계정에 잔액이 있습니다.
  • 컨테이너 재빌드
  • LLM 페르소나 및 사용자 삭제 후 재생성
  • LLM 모델 삭제 후 생성
  • 새로운 API 토큰 키 생성
  • 컨테이너 내부에서 SSL 및 인증서가 업데이트되었는지 확인
  • 컨테이너에 로그인하여 bash 및 curl을 사용하여 API 호출 (성공)
  • rails 콘솔 RAILS_ENV=production bundle exec rails console에 로그인하여 http 객체를 사용해 OpenAI API 호출 (성공)
  • claude-3.5-sonnet에 대한 Anthropic API 호출 (성공)

재현 단계:

최신 Discourse를 사용하여 새로운 컨테이너 빌드를 생성하고 plugins에 Discourse AI 플러그인을 추가합니다:

  ...
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/discourse-ai.git

다음과 같이 OpenAI LLM 및 임베딩 모델을 구성합니다:

  • GPT4 Omni, GPT4 Omni Mini
    • 모든 기본값 유지, API 키 삽입
    • 토큰: 64000
    • “테스트 실행” 클릭, 응답 대기, 때로는 성공하지만 종종 “Internal Server Error” 발생. 성공하더라도 페르소나와 채팅을 시도하면 Inference LLM Model 스택 트레이스가 나타남
  • text-embedding-ada-002, text-embedding-3-large
    • 성공적으로 저장되지만, 오류 로그 생성, 5분마다 반복적으로 발생

Internal Server Error 스택 트레이스

Internal Server Error 스택 트레이스
Message (2 copies reported)
Errno::ECONNRESET (Connection reset by peer)
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/contentsecurity_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:26: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'
Backtrace
openssl (3.3.0) lib/openssl/buffering.rb:217:in `sysread_nonblock'
openssl (3.3.0) lib/openssl/buffering.rb:217:in `read_nonblock'
net-protocol (0.2.2) lib/net/protocol.rb:218:in `rbuf_fill'
net-protocol (0.2.2) lib/net/protocol.rb:199:in `readuntil'
net-protocol (0.2.2) lib/net/protocol.rb:209:in `readline'
net-http (0.6.0) lib/net/http/response.rb:625:in `read_chunked'
net-http (0.6.0) lib/net/http/response.rb:595:in `block in read_body_0'
net-http (0.6.0) lib/net/http/response.rb:570:in `inflater'
net-http (0.6.0) lib/net/http/response.rb:593:in `read_body_0'
net-http (0.6.0) lib/net/http/response.rb:363:in `read_body'
plugins/discourse-ai/lib/completions/endpoints/base.rb:374:in `non_streaming_response'
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:44:in `step' 
rack-mini-profiler (3.3.1) lib/patches/net_patches.rb:18:in `request_with_mini_profiler' 
(eval at /var/www/discourse/lib/method_profiler.rb:38):12:in `request'
plugins/discourse-ai/lib/completions/endpoints/base.rb:122: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'
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/contentsecurity_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:26: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'
plugins/discourse-prometheus/lib/middleware/metrics.rb:14: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>'

로그를 확인하면 다음과 같은 오류가 있습니다:

임베딩 모델

로그의 오류 메시지: (5분마다) Connection reset by peer (Faraday::ConnectionFailed)

application_version: 00907363d4b290df1c755df1a2494b95265e40b4

job: Jobs::EmbeddingsBackfill

임베딩 모델 오류 스택 트레이스

임베딩 모델 오류 스택 트레이스
Job exception: 5 errors
Connection reset by peer (Faraday::ConnectionFailed)
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/openssl-3.3.0/lib/openssl/buffering.rb:217:in `sysread_nonblock'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/openssl-3.3.0/lib/openssl/buffering.rb:217:in `read_nonblock'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/net-protocol-0.2.2/lib/net/protocol.rb:218:in `rbuf_fill'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/net-protocol-0.2.2/lib/net/protocol.rb:199:in `readuntil'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/net-protocol-0.2.2/lib/net/protocol.rb:209:in `readline'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/net-http-0.6.0/lib/net/http/response.rb:625:in `read_chunked'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/net-http-0.6.0/lib/net/http/response.rb:595:in `block in read_body_0'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/net-http-0.6.0/lib/net/http/response.rb:570:in `inflater'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/net-http-0.6.0/lib/net/http/response.rb:593:in `read_body_0'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/net-http-0.6.0/lib/net/http/response.rb:363:in `read_body'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/net-http-0.6.0/lib/net/http/response.rb:401:in `body'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/net-http-0.6.0/lib/net/http/response.rb:321:in `reading_body'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/net-http-0.6.0/lib/net/http.rb:2430:in `transport_request'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/net-http-0.6.0/lib/net/http.rb:2384:in `request'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rack-mini-profiler-3.3.1/lib/patches/net_patches.rb:19:in `block in request_with_mini_profiler'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rack-mini-profiler-3.3.1/lib/mini_profiler/profiling_methods.rb:50:in `step'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rack-mini-profiler-3.3.1/lib/patches/net_patches.rb:18:in `request_with_mini_profil...
Backtrace
concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/promises.rb:1268:in `raise' 
concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/promises.rb:1268:in `wait_until_resolved!' 
concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/promises.rb:998:in `value!' 
/var/www/discourse/plugins/discourse-ai/lib/embeddings/vector.rb:50:in `gen_bulk_reprensentations' 
/var/www/discourse/plugins/discourse-ai/app/jobs/scheduled/embeddings_backfill.rb:134:in `block in populate_topic_embeddings' 
/var/www/discourse/plugins/discourse-ai/app/jobs/scheduled/embeddings_backfill.rb:133:in `each' 
/var/www/discourse/plugins/discourse-ai/app/jobs/scheduled/embeddings_backfill.rb:133:in `each_slice' 
/var/www/discourse/plugins/discourse-ai/app/jobs/scheduled/embeddings_backfill.rb:133:in `populate_topic_embeddings' 
/var/www/discourse/plugins/discourse-ai/app/jobs/scheduled/embeddings_backfill.rb:36:in `execute' 
/var/www/discourse/app/jobs/base.rb:316:in `block (2 levels) in perform' 
rails_multisite-6.1.0/lib/rails_multisite/connection_management/null_instance.rb:49:in `with_connection'
rails_multisite-6.1.0/lib/rails_multisite/connection_management.rb:21:in `with_connection'
/var/www/discourse/app/jobs/base.rb:303:in `block in perform' 
/var/www/discourse/app/jobs/base.rb:299:in `each' 
/var/www/discourse/app/jobs/base.rb:299:in `perform' 
/var/www/discourse/app/jobs/base.rb:379:in `perform' 
mini_scheduler-0.18.0/lib/mini_scheduler/manager.rb:137:in `process_queue' 
mini_scheduler-0.18.0/lib/mini_scheduler/manager.rb:77:in `worker_loop' 
mini_scheduler-0.18.0/lib/mini_scheduler/manager.rb:63:in `block (2 levels) in ensure_worker_threads' 

추론 LLM 모델

로그의 오류 메시지: Job exception: Connection reset by peer

application_version: 00907363d4b290df1c755df1a2494b95265e40b4

job: Jobs::CreateAiReply

LLM 모델 오류 스택 트레이스

LLM 모델 오류 스택 트레이스
Message
Job exception: Connection reset by peer
Backtrace
openssl-3.3.0/lib/openssl/buffering.rb:217:in `sysread_nonblock' 
openssl-3.3.0/lib/openssl/buffering.rb:217:in `read_nonblock' 
net-protocol-0.2.2/lib/net/protocol.rb:218:in `rbuf_fill' 
net-protocol-0.2.2/lib/net/protocol.rb:199:in `readuntil' 
net-protocol-0.2.2/lib/net/protocol.rb:209:in `readline' 
net-http-0.6.0/lib/net/http/response.rb:625:in `read_chunked' 
net-http-0.6.0/lib/net/http/response.rb:595:in `block in read_body_0' 
net-http-0.6.0/lib/net/http/response.rb:570:in `inflater' 
net-http-0.6.0/lib/net/http/response.rb:593:in `read_body_0' 
net-http-0.6.0/lib/net/http/response.rb:363:in `read_body' 
/var/www/discourse/plugins/discourse-ai/lib/completions/endpoints/base.rb:374:in `non_streaming_response' 
/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' 
(eval at /var/www/discourse/lib/method_profiler.rb:38):5:in `request'
/var/www/discourse/plugins/discourse-ai/lib/completions/endpoints/base.rb:122: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:105:in `perform_completion!' 
/var/www/discourse/plugins/discourse-ai/lib/completions/endpoints/open_ai.rb:44:in `perform_completion!' 
/var/www/discourse/plugins/discourse-ai/lib/completions/llm.rb:281:in `generate' 
/var/www/discourse/plugins/discourse-ai/lib/ai_bot/bot.rb:65:in `get_updated_title' 
/var/www/discourse/plugins/discourse-ai/lib/ai_bot/playground.rb:252:in `title_playground' 
/var/www/discourse/plugins/discourse-ai/lib/ai_bot/playground.rb:561:in `ensure in reply_to' 
/var/www/discourse/plugins/discourse-ai/lib/ai_bot/playground.rb:561:in `reply_to' 
/var/www/discourse/plugins/discourse-ai/app/jobs/regular/create_ai_reply.rb:18:in `execute' 
/var/www/discourse/app/jobs/base.rb:316:in `block (2 levels) in perform' 
rails_multisite-6.1.0/lib/rails_multisite/connection_management/null_instance.rb:49:in `with_connection'
rails_multisite-6.1.0/lib/rails_multisite/connection_management.rb:21:in `with_connection'
/var/www/discourse/app/jobs/base.rb:303:in `block in perform' 
/var/www/discourse/app/jobs/base.rb:299:in `each' 
/var/www/discourse/app/jobs/base.rb:299:in `perform' 
sidekiq-6.5.12/lib/sidekiq/processor.rb:202:in `execute_job' 
sidekiq-6.5.12/lib/sidekiq/processor.rb:170:in `block (2 levels) in process' 
sidekiq-6.5.12/lib/sidekiq/middleware/chain.rb:177:in `block in invoke' 
/var/www/discourse/lib/sidekiq/pausable.rb:132:in `call' 
sidekiq-6.5.12/lib/sidekiq/middleware/chain.rb:179:in `block in invoke' 
sidekiq-6.5.12/lib/sidekiq/middleware/chain.rb:182:in `invoke' 
sidekiq-6.5.12/lib/sidekiq/processor.rb:169:in `block in process' 
sidekiq-6.5.12/lib/sidekiq/processor.rb:136:in `block (6 levels) in dispatch' 
sidekiq-6.5.12/lib/sidekiq/job_retry.rb:113:in `local' 
sidekiq-6.5.12/lib/sidekiq/processor.rb:135:in `block (5 levels) in dispatch' 
sidekiq-6.5.12/lib/sidekiq.rb:44:in `block in <module:Sidekiq>' 
sidekiq-6.5.12/lib/sidekiq/processor.rb:131:in `block (4 levels) in dispatch' 
sidekiq-6.5.12/lib/sidekiq/processor.rb:263:in `stats' 
sidekiq-6.5.12/lib/sidekiq/processor.rb:126:in `block (3 levels) in dispatch' 
sidekiq-6.5.12/lib/sidekiq/job_logger.rb:13:in `call' 
sidekiq-6.5.12/lib/sidekiq/processor.rb:125:in `block (2 levels) in dispatch' 
sidekiq-6.5.12/lib/sidekiq/job_retry.rb:80:in `global' 
sidekiq-6.5.12/lib/sidekiq/processor.rb:124:in `block in dispatch' 
sidekiq-6.5.12/lib/sidekiq/job_logger.rb:39:in `prepare' 
sidekiq-6.5.12/lib/sidekiq/processor.rb:123:in `dispatch' 
sidekiq-6.5.12/lib/sidekiq/processor.rb:168:in `process' 
sidekiq-6.5.12/lib/sidekiq/processor.rb:78:in `process_one' 
sidekiq-6.5.12/lib/sidekiq/processor.rb:68:in `run' 
sidekiq-6.5.12/lib/sidekiq/component.rb:8:in `watchdog' 
sidekiq-6.5.12/lib/sidekiq/component.rb:17:in `block in safe_thread' 

아무 아이디어나 제안 등이 있다면 매우 환영합니다

1개의 좋아요

지난 한 달 동안 이 사이트에서 OpenAI API에 2,000건 이상의 요청을 보냈지만, 로그에 그러한 오류는 없습니다.

우리가 호스팅하는 OpenAI를 대량으로 사용하는 다른 사이트에는 지난 한 달 동안 80,000건의 요청이 있었고, Faraday 오류는 전혀 없으며, 해당 기간 동안 “Connection Reset by Peer” 오류는 단 두 건만 발생했습니다.

서버의 네트워크 구성에 문제가 있는 것은 아닌지 확인해 보셨나요? 한 번은 불량한 NIC 드라이버 때문에 Errno::ECONNRESET (Connection reset by peer) 오류가 발생한 적이 있습니다.

확인해 보겠습니다.

1개의 좋아요

말씀하신 대로, 처음에는 네트워크 스택 문제인 줄 알았지만, 해당 컨테이너에서 반복적으로 OpenAI API를 호출하면 정상적으로 동작합니다.

또한, 이는 2월 21일 기준으로 매우 최근의 빌드에서 테스트한 것입니다.

이를 증명하기 위해(토큰 소모를 감수하고) OpenAI 네트워크 스택을 확인하기 위한 간단한 스크립트를 작성했습니다.

  • 600초(10분) 동안 실행됩니다.
  • 초당 1회씩 채팅 완성(chat completion) 호출을 수행합니다.
  • 캐시를 피하기 위해 프롬프트를 변경합니다.

컨테이너 내부에서 ./launcher enter app을 실행하고, 아래 스크립트를 저장한 후 chmod +x test_openai.sh로 실행 권한을 부여하고, OPENAI_API_KEY=.... ./test_openai.sh로 실행하세요.

test_openai.sh
#!/bin/bash

# 실행 시간
DURATION_SECS=600

# 카운터 초기화
successful=0
unsuccessful=0
declare -A error_messages

# 백분율 계산 함수
calc_percentage() {
    local total=$(($1 + $2))
    if [ $total -eq 0 ]; then
        echo "0.00"
    else
        echo "scale=2; ($2 * 100) / $total" | bc
    fi
}

# 통계 출력 함수
print_stats() {
    local percent=$(calc_percentage $successful $unsuccessful)
    echo "-------------------"
    echo "성공한 호출: $successful"
    echo "실패한 호출: $unsuccessful"
    echo "실패율: ${percent}%"
    echo "에러 메시지:"
    for error in "${!error_messages[@]}"; do
        echo "  - $error (${error_messages[$error]} 회)"
    done
}

end_time=$((SECONDS + DURATION_SECS))

counter=1
while [ $SECONDS -lt $end_time ]; do
    # 타임아웃과 함께 API 호출 수행
    response=$(curl -s -w "\n%{http_code}" \
        -X POST \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer $OPENAI_API_KEY" \
        -d "{
            \"model\": \"gpt-4o-mini\",
            \"messages\": [{\"role\": \"user\", \"content\": \"Use this number to choose a one word response: $counter\"}]
        }" \
        --connect-timeout 5 \
        --max-time 10 \
        https://api.openai.com/v1/chat/completions 2>&1)

    # 마지막 줄(상태 코드)과 응답 본문 가져오기
    http_code=$(echo "$response" | tail -n1)
    body=$(echo "$response" | sed '$d')

    # 호출이 성공했는지 확인
    if [ "$http_code" = "200" ]; then
        ((successful++))
    else
        ((unsuccessful++))
        # 에러 메시지 추출
        error_msg=$(echo "$body" | grep -o '"message":"[^"]*"' | cut -d'"' -f4)
        if [ -z "$error_msg" ]; then
            error_msg="Connection error: $body"
        fi
        # 에러 메시지 카운터 증가
        ((error_messages["$error_msg"]++))
    fi

    # 현재 통계 출력
    print_stats

    ((counter++))
    
    # 다음 호출 전 1초 대기
    sleep 1
done

테스트 스크립트 실행 결과, 실패율은 0.5% 미만으로, 해당 규모에서는 허용 가능한 수준이었습니다.

이로써 문제는 컨테이너나 이를 구동하는 네트워크 스택이 아니라 Discourse 소프트웨어 자체에 있음을 알 수 있습니다.

최근 커밋으로 해결되지 않았다면, 더 자세히 조사해 보겠습니다.

2개의 좋아요

o1-mini와 o1-preview 주변의 회귀 버그를 여기에서 수정했습니다:

다만 SSL 문제에 대해서는 이해가 잘 안 됩니다. 우리는 여기서 기초 라이브러리를 변경한 적이 없거든요.

이것이 스트리밍과 관련이 있을 수 있으니, OpenAI LLM에서 스트리밍을 비활성화해 보시고 문제가 해결되는지 확인해 보세요. 해당 테스트에서는 스트리밍을 사용하지 않고 gpt-4o-mini를 사용하고 있습니다.

3개의 좋아요

정말 훌륭합니다! 잘 하셨습니다!

진단하는 과정에서 또 다른 버그를 발견했습니다. LLM 설정 페이지(/admin/plugins/discourse-ai/ai-llms/%/edit)에서 “네이티브 도구 지원 비활성화 (XML 기반 도구 사용) (선택)” 또는 “스트리밍 완료 비활성화 (스트리밍을 비스트리밍 요청으로 변환)” 옵션 중 하나를 선택하고 저장 버튼을 클릭하면 "성공!"이라는 임시 토스트 알림이 표시되지만, 페이지를 새로고침하면 두 옵션 중 하나 또는 둘 다 해제되어 있습니다.

연결 리셋 문제는 여전히 지속되고 있으며 저는 여전히 조사 중이지만, Ruby 코드(FinalDestination / DNS 이름 해석 / Faraday)의 소켓 처리와 Debian 12 컨테이너가 Ubuntu 24.04 VM에서 실행되는 환경이 결합된 것으로 보입니다.

테스트용 Ubuntu 22.04 VM을 설정해 보았더니 문제가 없으며, 모든 임베딩과 추론이 완벽하게 작동합니다. 리셋 현상을 한 번도 목격하지 못했습니다.

계속해서 문제를 파헤쳐 보겠습니다. 아마도 Ubuntu 24.04가 netplan으로 TCP 스택을 관리하는 새로운 방식과 관련이 있을 수도 있습니다.

2개의 좋아요

감사합니다. 오늘 영속성 문제를 해결했습니다. 업그레이드 후 다시 시도해 주세요.

3개의 좋아요

자, 업데이트를 조금 하겠습니다. 기업 IP 범위에서 OpenAI API와 직접 연결을 설정하는 데 실패했습니다. Cloudflare가 TLS 직후 약 1ms 뒤에 RST 패킷을 전송했기 때문입니다.

그래서 OpenAI API 엔드포인트의 URL 드롭인 대체재로 Cloudflare AI Gateway를 설정했는데, LLM 구성과 완벽하게 작동합니다.

Cloudflare에는 문서화되지 않은 레이트 리밋 정책이 있는 것 같습니다. 이는 알려지지 않은 IP 범위(예: Azure, AWS, GCP 등)에서 발동됩니다. Embeddings의 100개 연결 풀이 이 한도를 초과하게 되었습니다.

참고로, Cloudflare에는 Authenticated Gateway라는 기능이 있어 특수 헤더 토큰을 추가합니다.

해당 문서에서 발췌한 내용입니다:

curl https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/openai/chat/completions \
  --header 'cf-aig-authorization: Bearer {CF_AIG_TOKEN}' \
  --header 'Authorization: Bearer OPENAI_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{"model": "gpt-4o" ........

LLM 구성 화면에서 LLM별 헤더를 추가할 수 있는 기능이 있다면 정말 좋겠습니다.

그렇게 하면 우리가 수행하는 모든 호출에 대해 LLM에 cf-aig-authorization 키와 값을 추가할 수 있을 것입니다.

이건 좀 까다로운 문제예요. 엣지 케이스를 위해 너무 많은 UI를 부담해야 하거든요.

혹시 openrouter.ai를 시도해 볼 수 있을까요? 이 문제도 해결될 수 있을 것 같아요.

임의의 헤더를 허용하는 것에 대해 원칙적으로 반대하는 건 아니지만, 이건 아주 고급 설정이에요. 숨겨진 사이트 설정 뒤에 두면 괜찮을 것 같아요 (고급 UI를 활성화하는 사이트 설정).

이 회사가 오픈소스 플러그인에 대한 이 기여를 주도할 수 있을까요?

1개의 좋아요

기여(컨트리뷰션) 승인을 아직 받지 못했지만, 계속 노력해 보겠습니다. 지금까지 도움을 주셔서 감사합니다!