diff --git a/.gitea/workflows/main.yaml b/.gitea/workflows/main.yaml index 47c8e1a..6496809 100644 --- a/.gitea/workflows/main.yaml +++ b/.gitea/workflows/main.yaml @@ -7,80 +7,27 @@ on: workflow_dispatch: {} env: - REGISTRY_HOST: git.ivanch.me - REGISTRY_USERNAME: ivanch - IMAGE: ${{ env.REGISTRY_HOST }}/ivanch/recommender - KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }} + IMAGE: git.ivanch.me/ivanch/recommender jobs: - build_recommender: - name: Build Recommender Image - runs-on: ubuntu-22.04 - - steps: - - name: Check out repository - uses: actions/checkout@v2 - - - name: Log in to Container Registry - run: | - echo "${{ secrets.REGISTRY_PASSWORD }}" \ - | docker login "${{ env.REGISTRY_HOST }}" \ - -u "${{ env.REGISTRY_USERNAME }}" \ - --password-stdin - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Build and Push Multi-Arch Image - uses: docker/build-push-action@v6 - with: - push: true - context: . - platforms: linux/amd64,linux/arm64 - tags: | - ${{ env.IMAGE }}:latest - - deploy_recommender: - name: Deploy Recommender (internal) + build: + name: Build Image runs-on: ubuntu-amd64 - needs: build_recommender steps: - - name: Check KUBE_CONFIG validity - run: | - if [ -z "${KUBE_CONFIG}" ] || [ "${KUBE_CONFIG}" = "" ] || [ "${KUBE_CONFIG// }" = "" ]; then - echo "KUBE_CONFIG is not set or is empty." - exit 1 - fi + - uses: actions/checkout@v4 + - uses: https://git.ivanch.me/ivanch/pipeline-actions/build-and-push@main + with: + image: ${{ env.IMAGE }} + registry_password: ${{ secrets.REGISTRY_PASSWORD }} + ssh_key: ${{ secrets.SSH_KEY_DOCKERBUILD }} - - name: Check out repository - uses: actions/checkout@v2 - - - name: Download and install dependencies - run: | - apt-get update -y - apt-get install -y curl - curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" - install -m 0755 kubectl /usr/local/bin/kubectl - kubectl version --client - - - name: Set up kubeconfig - run: | - cd deploy - echo "$KUBE_CONFIG" > kubeconfig.yaml - env: - KUBE_CONFIG: ${{ env.KUBE_CONFIG }} - - - name: Check connection to cluster - run: | - cd deploy - kubectl --kubeconfig=kubeconfig.yaml cluster-info - - - name: Apply Recommender deployment - run: | - cd deploy - kubectl --kubeconfig=kubeconfig.yaml apply -f recommender.yaml - - - name: Rollout restart - run: | - cd deploy - kubectl --kubeconfig=kubeconfig.yaml rollout restart deployment recommender -n media + deploy: + name: Deploy (internal) + runs-on: ubuntu-amd64 + needs: build + steps: + - uses: https://git.ivanch.me/ivanch/pipeline-actions/deploy-restart@main + with: + kube_config: ${{ secrets.KUBE_CONFIG }} + deployment_name: recommender + namespace: media diff --git a/.gitignore b/.gitignore index 77425fe..1e3cc62 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,10 @@ documents/ # OS Thumbs.db + +# Deploy +deploy/terraform/.terraform +deploy/terraform/*.tfstate +deploy/terraform/*.tfstate.* +deploy/terraform/*.tfplan +deploy/terraform/.terraform.lock.hcl \ No newline at end of file diff --git a/deploy/recommender.yaml b/deploy/recommender.yaml deleted file mode 100644 index 9e3dc8b..0000000 --- a/deploy/recommender.yaml +++ /dev/null @@ -1,83 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: recommender - namespace: media -spec: - replicas: 1 - selector: - matchLabels: - app: recommender - template: - metadata: - labels: - app: recommender - spec: - containers: - - name: recommender - image: git.ivanch.me/ivanch/recommender:latest - imagePullPolicy: Always - ports: - - containerPort: 80 - env: - - name: OPENAI_API_KEY - valueFrom: - secretKeyRef: - name: recommender-secrets - key: OPENAI_API_KEY - - name: DATABASE_URL - valueFrom: - secretKeyRef: - name: recommender-secrets - key: DATABASE_URL - - name: BEARER_TOKEN - valueFrom: - secretKeyRef: - name: recommender-secrets - key: BEARER_TOKEN - - name: PROVIDER_URL - value: "https://openrouter.ai/api/v1" - - name: MODEL_NAME - value: "openai/gpt-5.4" - - name: AI_PROVIDER - value: "GENERIC" - resources: - requests: - memory: "256Mi" - cpu: "500m" - limits: - memory: "512Mi" - cpu: "1" ---- -apiVersion: v1 -kind: Service -metadata: - name: recommender - namespace: media -spec: - selector: - app: recommender - ports: - - port: 80 - targetPort: 80 ---- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: recommender - namespace: media - labels: - app.kubernetes.io/name: recommender -spec: - ingressClassName: nginx - rules: - - host: "recommender.haven" - http: - paths: - - path: "/" - pathType: Prefix - backend: - service: - name: recommender - port: - number: 80 diff --git a/packages/backend/.env b/packages/backend/.env index 478c0a5..175fa56 100644 --- a/packages/backend/.env +++ b/packages/backend/.env @@ -4,13 +4,7 @@ DATABASE_URL=postgres://user:password@localhost:5432/recommender -# AI provider selection: OPENAI (default) or GENERIC -AI_PROVIDER=OPENAI - -# OpenAI provider settings (used when AI_PROVIDER=OPENAI) OPENAI_API_KEY=your-openai-api-key-here -# Generic provider settings (used when AI_PROVIDER=GENERIC) +# provider settings PROVIDER_URL=https://your-provider.example.com/v1 -BEARER_TOKEN=your-bearer-token -MODEL_NAME=your-model-name diff --git a/packages/backend/src/agent.ts b/packages/backend/src/agent.ts index 701d7b3..1d1b206 100644 --- a/packages/backend/src/agent.ts +++ b/packages/backend/src/agent.ts @@ -2,26 +2,17 @@ import OpenAI from 'openai'; import * as dotenv from 'dotenv'; dotenv.config({ path: ['.env.local', '.env'] }); -const AI_PROVIDER = process.env.AI_PROVIDER ?? 'OPENAI'; -const isGeneric = AI_PROVIDER === 'GENERIC'; +export const openai = new OpenAI({ + apiKey: process.env.BEARER_TOKEN, + baseURL: process.env.PROVIDER_URL, + timeout: 600000, // 10 minutes + maxRetries: 3, +}); -export const openai = isGeneric - ? new OpenAI({ - apiKey: process.env.BEARER_TOKEN, - baseURL: process.env.PROVIDER_URL, - timeout: 600000, // 10 minutes - maxRetries: 3, - }) - : new OpenAI({ - apiKey: process.env.OPENAI_API_KEY, - timeout: 600000, // 10 minutes - maxRetries: 3, - }); - -export const defaultModel = isGeneric ? (process.env.MODEL_NAME ?? 'default') : 'gpt-5.4'; -export const miniModel = isGeneric ? (process.env.MODEL_NAME ?? 'default') : 'gpt-5.4-mini'; -export const serviceOptions = isGeneric ? {} : { service_tier: 'flex' as const }; -export const supportsWebSearch = !isGeneric; +export const defaultModel = process.env.MODEL_NAME ?? 'gpt-5.4'; +export const miniModel = process.env.MODEL_NAME ?? 'gpt-5.4-mini'; +export const serviceOptions = { service_tier: 'flex' as const }; +export const supportsWebSearch = true; function isJsonParseError(err: unknown): boolean { if (err instanceof SyntaxError) return true;