feat: CI/CD pipeline + Learning/Medicine/Travel services
- Add Gitea Actions workflow for automated build & deploy - Add K8s manifests: webui, travel-svc, medicine-svc, sandbox-svc - Update kustomization for localhost:5000 registry - Add ingress for gooseek.ru and api.gooseek.ru - Learning cabinet with onboarding, courses, sandbox integration - Medicine service with symptom analysis and doctor matching - Travel service with itinerary planning - Server setup scripts (NVIDIA/CUDA, K3s, Gitea runner) Made-with: Cursor
This commit is contained in:
120
backend/cmd/medicine-svc/main.go
Normal file
120
backend/cmd/medicine-svc/main.go
Normal file
@@ -0,0 +1,120 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/cors"
|
||||
"github.com/gofiber/fiber/v2/middleware/logger"
|
||||
"github.com/gooseek/backend/internal/llm"
|
||||
"github.com/gooseek/backend/internal/medicine"
|
||||
"github.com/gooseek/backend/pkg/middleware"
|
||||
)
|
||||
|
||||
func main() {
|
||||
llmClient := createLLMClient()
|
||||
if llmClient == nil {
|
||||
log.Println("medicine-svc: no LLM configured, fallback mode enabled")
|
||||
}
|
||||
|
||||
svc := medicine.NewService(medicine.ServiceConfig{
|
||||
LLM: llmClient,
|
||||
SearXNGURL: getEnv("SEARXNG_URL", "http://searxng:8080"),
|
||||
Timeout: 20 * time.Second,
|
||||
})
|
||||
|
||||
app := fiber.New(fiber.Config{
|
||||
ReadTimeout: 60 * time.Second,
|
||||
WriteTimeout: 120 * time.Second,
|
||||
})
|
||||
|
||||
app.Use(logger.New())
|
||||
app.Use(cors.New())
|
||||
|
||||
app.Get("/health", func(c *fiber.Ctx) error {
|
||||
return c.JSON(fiber.Map{"status": "ok", "service": "medicine-svc"})
|
||||
})
|
||||
|
||||
jwtOptional := middleware.JWTConfig{
|
||||
Secret: os.Getenv("JWT_SECRET"),
|
||||
AuthSvcURL: getEnv("AUTH_SVC_URL", "http://auth-svc:3050"),
|
||||
AllowGuest: true,
|
||||
}
|
||||
|
||||
api := app.Group("/api/v1/medicine")
|
||||
api.Post("/consult", middleware.JWT(jwtOptional), func(c *fiber.Ctx) error {
|
||||
var req medicine.ConsultRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "Invalid request body"})
|
||||
}
|
||||
if req.Symptoms == "" {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "symptoms is required"})
|
||||
}
|
||||
|
||||
c.Set("Content-Type", "application/x-ndjson")
|
||||
c.Set("Cache-Control", "no-cache")
|
||||
c.Set("Transfer-Encoding", "chunked")
|
||||
|
||||
c.Context().SetBodyStreamWriter(func(w *bufio.Writer) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 90*time.Second)
|
||||
defer cancel()
|
||||
if err := svc.StreamConsult(ctx, req, w); err != nil {
|
||||
log.Printf("medicine consult error: %v", err)
|
||||
}
|
||||
})
|
||||
return nil
|
||||
})
|
||||
|
||||
port := getEnvInt("PORT", 3037)
|
||||
log.Printf("medicine-svc listening on :%d", port)
|
||||
log.Fatal(app.Listen(fmt.Sprintf(":%d", port)))
|
||||
}
|
||||
|
||||
func createLLMClient() llm.Client {
|
||||
cfg := llm.ProviderConfig{
|
||||
ProviderID: getEnv("LLM_PROVIDER", "timeweb"),
|
||||
ModelKey: getEnv("LLM_MODEL", "gpt-4o-mini"),
|
||||
BaseURL: os.Getenv("TIMEWEB_API_BASE_URL"),
|
||||
APIKey: os.Getenv("TIMEWEB_API_KEY"),
|
||||
AgentAccessID: os.Getenv("TIMEWEB_AGENT_ACCESS_ID"),
|
||||
}
|
||||
client, err := llm.NewClient(cfg)
|
||||
if err == nil {
|
||||
return client
|
||||
}
|
||||
if os.Getenv("OPENAI_API_KEY") != "" {
|
||||
openAIClient, openAIErr := llm.NewClient(llm.ProviderConfig{
|
||||
ProviderID: "openai",
|
||||
ModelKey: "gpt-4o-mini",
|
||||
APIKey: os.Getenv("OPENAI_API_KEY"),
|
||||
})
|
||||
if openAIErr == nil {
|
||||
return openAIClient
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getEnv(key, fallback string) string {
|
||||
if v := os.Getenv(key); v != "" {
|
||||
return v
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
func getEnvInt(key string, fallback int) int {
|
||||
v := os.Getenv(key)
|
||||
if v == "" {
|
||||
return fallback
|
||||
}
|
||||
var out int
|
||||
if _, err := fmt.Sscanf(v, "%d", &out); err != nil {
|
||||
return fallback
|
||||
}
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user