From 1e2b16f66c65766a3a1b156e6dee70d58f446512 Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Mon, 24 Jun 2024 13:44:42 +0300 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=93=A6=20Release:=20v0.1.0-rc.1=20(#2?= =?UTF-8?q?80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first major update with breaking changes to the language chat schemas and begging of work on instrumenting the gateway with OpenTelemetry. ### Added - πŸ”§ Use github.com/EinStack/glide as module name to support go install cmd (@gernest) - βœ¨πŸ”§ Setup Open Telemetry Metrics and Traces (#237) (@gernest) - πŸ”§ #221 Add B3 trace propagator (#242) (@gernest) - πŸ”§ #241 Support overriding OTEL resource attributes (#243) (@gernest) - πŸ”§ #248 Disable span and metrics by default (#254) (@gernest) - πŸ”§ #220 Instrument API server with observability signals (#255) (@gernest) - πŸ”§ #164 Make client connection pool configurable across all providers (#251) (@daesu) - πŸ”§ Instrument gateway process (#256) (@gernest) - πŸ”§ #262: adding connection pool for chat request and response (#271) (@tom-fitz) ### Changed - πŸ”§ #238 Implements human-readable durations in config (#253) (@ppmdo) - πŸ”§ #266: removing omitempty from response definition (#267) (@tom-fitz) #### Breaking Changes - πŸ”§ πŸ’₯ #235: Extended the non-streaming chat error schema with new fields to give clients more context around the error (#236) (@roma-glushko) - πŸ’₯ Convert all camelCase config fields to the snake_case in the provider configs (#260) (@roma-glushko) - ✨πŸ’₯ #153: Allow to pass multiple model-specific param overrides (#264) (@roma-glushko) ### Fixed - πŸ› #217: Set build info correctly in Glide images (#218) (@roma-glushko) ### Security - πŸ”’ Updated golang to 1.22.4 to address CVE-2024-24790 (#276) (@STAR-173) ### Miscellaneous - πŸ“ Defined a way to manage EinStack Glide project (#234) (@roma-glushko) - πŸ‘· #219: Setup local telemetry stack with Jaeger, Grafana, VictoriaMetrics and OTEL Collector (#225) (@roma-glushko) - πŸ‘·β€β™‚οΈ Added a new GH action to watch for glide activity stream (#239, #244) (@roma-glushko) - ✨ Switched to the new docs (@roma-glushko) - πŸ”§ #240: Automatically install air (#277, #270) (@ppmdo, @roma-glushko) --- .air.toml | 51 + .github/workflows/activity-notifications.yaml | 63 + .github/workflows/lint.yaml | 10 +- .github/workflows/release.yaml | 2 +- .github/workflows/vuln.yaml | 2 +- .go-version | 2 +- CHANGELOG.md | 49 +- CONTRIBUTING.md | 21 + Makefile | 37 +- README.md | 19 +- ROADMAP.md | 58 +- compose.yaml | 61 + .../\360\237\222\254 Chat Stream.bru" | 11 - .../Language API/\360\237\222\254 Chat.bru" | 21 - .../\360\237\224\247 Router List.bru" | 21 - docs/api/bruno.json | 5 - docs/api/environments/Development.bru | 3 - "docs/api/\360\237\224\247 Health.bru" | 11 - docs/docs.go | 702 +----- .../einstack-project-management.excalidraw | 1997 +++++++++++++++++ docs/images/einstack-project-management.png | Bin 0 -> 585692 bytes docs/swagger.json | 702 +----- docs/swagger.yaml | 503 +---- go.mod | 54 +- go.sum | 117 +- images/Makefile | 3 +- images/alpine.Dockerfile | 4 +- images/distroless.Dockerfile | 4 +- images/redhat.Dockerfile | 4 +- images/ubuntu.Dockerfile | 4 +- main.go | 2 +- pkg/api/config.go | 2 +- pkg/api/http/config.go | 2 +- pkg/api/http/handlers.go | 71 +- pkg/api/http/schemas.go | 15 - pkg/api/http/server.go | 12 +- pkg/api/schemas/chat.go | 90 +- pkg/api/schemas/chat_stream.go | 58 +- pkg/api/schemas/chat_test.go | 170 ++ pkg/api/schemas/errors.go | 79 + pkg/api/schemas/health_checks.go | 5 + pkg/api/schemas/pool.go | 39 + pkg/api/schemas/routers.go | 9 + pkg/api/servers.go | 6 +- pkg/cmd/cli.go | 10 +- pkg/config/config.go | 8 +- pkg/gateway.go | 24 +- pkg/providers/anthropic/chat.go | 75 +- pkg/providers/anthropic/chat_stream.go | 7 +- pkg/providers/anthropic/client.go | 23 +- pkg/providers/anthropic/client_test.go | 18 +- pkg/providers/anthropic/config.go | 14 +- pkg/providers/anthropic/errors.go | 5 +- pkg/providers/azureopenai/chat.go | 68 +- pkg/providers/azureopenai/chat_stream.go | 41 +- pkg/providers/azureopenai/chat_stream_test.go | 22 +- pkg/providers/azureopenai/client.go | 27 +- pkg/providers/azureopenai/client_test.go | 32 +- pkg/providers/azureopenai/config.go | 13 +- pkg/providers/azureopenai/errors.go | 5 +- pkg/providers/azureopenai/schemas.go | 53 +- pkg/providers/bedrock/chat.go | 68 +- pkg/providers/bedrock/chat_stream.go | 7 +- pkg/providers/bedrock/client.go | 21 +- pkg/providers/bedrock/client_test.go | 12 +- pkg/providers/bedrock/config.go | 12 +- pkg/providers/clients/config.go | 16 +- pkg/providers/clients/config_test.go | 40 + pkg/providers/clients/errors.go | 1 + pkg/providers/clients/stream.go | 2 +- pkg/providers/cohere/chat.go | 53 +- pkg/providers/cohere/chat_stream.go | 44 +- pkg/providers/cohere/chat_stream_test.go | 22 +- pkg/providers/cohere/client.go | 23 +- pkg/providers/cohere/client_test.go | 12 +- pkg/providers/cohere/config.go | 10 +- pkg/providers/cohere/errors.go | 5 +- pkg/providers/cohere/finish_reason.go | 13 +- pkg/providers/cohere/schemas.go | 49 +- pkg/providers/config.go | 29 +- pkg/providers/lang.go | 33 +- pkg/providers/octoml/chat.go | 101 +- pkg/providers/octoml/chat_stream.go | 7 +- pkg/providers/octoml/client.go | 17 +- pkg/providers/octoml/client_test.go | 33 +- pkg/providers/octoml/config.go | 13 +- pkg/providers/octoml/errors.go | 5 +- pkg/providers/ollama/chat.go | 99 +- pkg/providers/ollama/chat_stream.go | 7 +- pkg/providers/ollama/client.go | 23 +- pkg/providers/ollama/client_test.go | 77 +- pkg/providers/ollama/config.go | 12 +- .../ollama/testdata/chat.success.json | 4 +- pkg/providers/openai/chat.go | 55 +- pkg/providers/openai/chat_stream.go | 36 +- pkg/providers/openai/chat_stream_test.go | 24 +- pkg/providers/openai/chat_test.go | 23 +- pkg/providers/openai/client.go | 23 +- pkg/providers/openai/config.go | 12 +- pkg/providers/openai/errors.go | 5 +- pkg/providers/openai/finish_reasons.go | 13 +- pkg/providers/openai/schemas.go | 60 +- pkg/providers/provider.go | 3 +- pkg/providers/testing/lang.go | 32 +- pkg/providers/testing/models.go | 7 +- pkg/routers/config.go | 19 +- pkg/routers/config_test.go | 26 +- pkg/routers/health/tracker.go | 2 +- pkg/routers/health/tracker_test.go | 2 +- pkg/routers/latency/config.go | 2 +- pkg/routers/manager.go | 9 +- pkg/routers/retry/config.go | 18 +- pkg/routers/retry/config_test.go | 16 + pkg/routers/router.go | 41 +- pkg/routers/router_test.go | 60 +- pkg/routers/routing/least_latency.go | 4 +- pkg/routers/routing/least_latency_test.go | 5 +- pkg/routers/routing/priority.go | 2 +- pkg/routers/routing/priority_test.go | 5 +- pkg/routers/routing/round_robin.go | 2 +- pkg/routers/routing/round_robin_test.go | 5 +- pkg/routers/routing/strategies.go | 2 +- pkg/routers/routing/weighted_round_robin.go | 2 +- .../routing/weighted_round_robin_test.go | 5 +- pkg/telemetry/telemetry.go | 100 +- pkg/telemetry/telemetry_test.go | 20 + tools/otel-col-config.yaml | 35 + 127 files changed, 4132 insertions(+), 2959 deletions(-) create mode 100644 .air.toml create mode 100644 .github/workflows/activity-notifications.yaml create mode 100644 compose.yaml delete mode 100644 "docs/api/Language API/\360\237\222\254 Chat Stream.bru" delete mode 100644 "docs/api/Language API/\360\237\222\254 Chat.bru" delete mode 100644 "docs/api/Language API/\360\237\224\247 Router List.bru" delete mode 100644 docs/api/bruno.json delete mode 100644 docs/api/environments/Development.bru delete mode 100644 "docs/api/\360\237\224\247 Health.bru" create mode 100644 docs/images/einstack-project-management.excalidraw create mode 100644 docs/images/einstack-project-management.png delete mode 100644 pkg/api/http/schemas.go create mode 100644 pkg/api/schemas/chat_test.go create mode 100644 pkg/api/schemas/errors.go create mode 100644 pkg/api/schemas/health_checks.go create mode 100755 pkg/api/schemas/pool.go create mode 100644 pkg/api/schemas/routers.go create mode 100644 tools/otel-col-config.yaml diff --git a/.air.toml b/.air.toml new file mode 100644 index 00000000..40b0a72e --- /dev/null +++ b/.air.toml @@ -0,0 +1,51 @@ +root = "." +testdata_dir = "testdata" +tmp_dir = "tmp" + +[build] + args_bin = ["-c ./config.dev.yaml"] + bin = "./dist/glide" + cmd = "make build" + delay = 1000 + exclude_dir = ["assets", "tmp", "vendor", "testdata"] + exclude_file = [] + exclude_regex = ["_test.go"] + exclude_unchanged = false + follow_symlink = false + full_bin = "" + include_dir = [] + include_ext = ["go", "tpl", "tmpl", "html"] + include_file = [] + kill_delay = "0s" + log = "build-errors.log" + poll = false + poll_interval = 0 + post_cmd = [] + pre_cmd = [] + rerun = false + rerun_delay = 500 + send_interrupt = false + stop_on_error = false + +[color] + app = "" + build = "yellow" + main = "magenta" + runner = "green" + watcher = "cyan" + +[log] + main_only = false + time = false + +[misc] + clean_on_exit = false + +[proxy] + app_port = 0 + enabled = false + proxy_port = 0 + +[screen] + clear_on_rebuild = false + keep_scroll = true diff --git a/.github/workflows/activity-notifications.yaml b/.github/workflows/activity-notifications.yaml new file mode 100644 index 00000000..1dd6ea28 --- /dev/null +++ b/.github/workflows/activity-notifications.yaml @@ -0,0 +1,63 @@ +name: Pull Request Activity Notifications + +on: + pull_request_target: + types: [opened, closed, reopened] + +jobs: + activity_notifications: + runs-on: ubuntu-latest + steps: + - name: Gather PR context + id: context + uses: actions/github-script@v4 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const pr = context.payload.pull_request; + const author = pr.user.login; + const project = context.payload.repository.full_name; + const action = context.payload.action; + const wasMerged = pr.merged; + + console.log(`Action: ${action}`); + console.log(`PR Author: ${author}`); + console.log(`Project: ${project}`); + console.log(`Was Merged?: ${wasMerged}`); + + core.setOutput('author', author); + core.setOutput('project', project); + core.setOutput('action', action); + core.setOutput('wasMerged', wasMerged); + + - name: Send Discord Notification for opened PR + if: ${{ github.event_name == 'pull_request' && github.event.action == 'opened' }} + uses: Ilshidur/action-discord@master + env: + DISCORD_WEBHOOK: ${{ secrets.ACTIVITY_DISCORD_WEBHOOK_URL }} + with: + args: "✨️[New Pull Request]\nProject: ${{ steps.context.outputs.project }}\nAuthor: ${{ steps.context.outputs.author }}\nLink: ${{ github.event.pull_request.html_url }}" + + - name: Send Discord Notification for closed PR + if: ${{ github.event_name == 'pull_request' && github.event.action == 'closed' && steps.context.outputs.wasMerged == 'false' }} + uses: Ilshidur/action-discord@master + env: + DISCORD_WEBHOOK: ${{ secrets.ACTIVITY_DISCORD_WEBHOOK_URL }} + with: + args: "🚫[Pull Request Closed]\nProject: ${{ steps.context.outputs.project }}\nAuthor: ${{ steps.context.outputs.author }}\nLink: ${{ github.event.pull_request.html_url }}" + + - name: Send Discord Notification for merged PR + if: ${{ github.event_name == 'pull_request' && github.event.action == 'closed' && steps.context.outputs.wasMerged == 'true' }} + uses: Ilshidur/action-discord@master + env: + DISCORD_WEBHOOK: ${{ secrets.ACTIVITY_DISCORD_WEBHOOK_URL }} + with: + args: "βœ…[Pull Request Merged]\nProject: ${{ steps.context.outputs.project }}\nAuthor: ${{ steps.context.outputs.author }}\nLink: ${{ github.event.pull_request.html_url }}" + + - name: Send Discord Notification for reopened PR + if: ${{ github.event_name == 'pull_request' && github.event.action == 'reopened' }} + uses: Ilshidur/action-discord@master + env: + DISCORD_WEBHOOK: ${{ secrets.ACTIVITY_DISCORD_WEBHOOK_URL }} + with: + args: "πŸ› οΈ[Pull Request Reopened]\nProject: ${{ steps.context.outputs.project }}\nAuthor: ${{ steps.context.outputs.author }}\nLink: ${{ github.event.pull_request.html_url }}" diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index e504ec17..4addd769 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -23,7 +23,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: "1.22" + go-version: "1.22.4" check-latest: true - name: Install @@ -56,7 +56,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: "1.22" + go-version: "1.22.4" check-latest: true - name: Build run: go build -v ./... @@ -70,7 +70,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: "1.22" + go-version: "1.22.4" check-latest: true - name: Install nilaway @@ -95,7 +95,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: "1.22" + go-version: "1.22.4" check-latest: true - name: Test @@ -121,7 +121,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: "1.22" + go-version: "1.22.4" check-latest: true - name: Generate OpenAPI Schema diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 69f01d09..e3d1d6ab 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -23,7 +23,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: 1.22 + go-version: 1.22.4 - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/vuln.yaml b/.github/workflows/vuln.yaml index aa26598c..d24340c1 100644 --- a/.github/workflows/vuln.yaml +++ b/.github/workflows/vuln.yaml @@ -27,7 +27,7 @@ jobs: - name: Install Go uses: actions/setup-go@v4 with: - go-version: '1.22.1' + go-version: '1.22.4' check-latest: true - name: Checkout diff --git a/.go-version b/.go-version index 71f7f51d..be02b337 100644 --- a/.go-version +++ b/.go-version @@ -1 +1 @@ -1.22 +1.22.4 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index da25bda2..700944ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,7 +41,51 @@ TBU TBU -## [0.0.3-rc2], [0.0.3] (Apr 17, 2024) +## [0.1.0-rc.1] (Jun 24, 2024) + +The first major update with breaking changes to the language chat schemas +and begging of work on instrumenting the gateway with OpenTelemetry. + +### Added + +- πŸ”§ Use github.com/EinStack/glide as module name to support go install cmd (@gernest) +- βœ¨πŸ”§ Setup Open Telemetry Metrics and Traces (#237) (@gernest) +- πŸ”§ #221 Add B3 trace propagator (#242) (@gernest) +- πŸ”§ #241 Support overriding OTEL resource attributes (#243) (@gernest) +- πŸ”§ #248 Disable span and metrics by default (#254) (@gernest) +- πŸ”§ #220 Instrument API server with observability signals (#255) (@gernest) +- πŸ”§ #164 Make client connection pool configurable across all providers (#251) (@daesu) +- πŸ”§ Instrument gateway process (#256) (@gernest) +- πŸ”§ #262: adding connection pool for chat request and response (#271) (@tom-fitz) + +### Changed + +- πŸ”§ #238 Implements human-readable durations in config (#253) (@ppmdo) +- πŸ”§ #266: removing omitempty from response definition (#267) (@tom-fitz) + +#### Breaking Changes + +- πŸ”§ πŸ’₯ #235: Extended the non-streaming chat error schema with new fields to give clients more context around the error (#236) (@roma-glushko) +- πŸ’₯ Convert all camelCase config fields to the snake_case in the provider configs (#260) (@roma-glushko) +- ✨πŸ’₯ #153: Allow to pass multiple model-specific param overrides (#264) (@roma-glushko) + +### Fixed + +- πŸ› #217: Set build info correctly in Glide images (#218) (@roma-glushko) + +### Security + +- πŸ”’ Updated golang to 1.22.4 to address CVE-2024-24790 (#276) (@STAR-173) + +### Miscellaneous + +- πŸ“ Defined a way to manage EinStack Glide project (#234) (@roma-glushko) +- πŸ‘· #219: Setup local telemetry stack with Jaeger, Grafana, VictoriaMetrics and OTEL Collector (#225) (@roma-glushko) +- πŸ‘·β€β™‚οΈ Added a new GH action to watch for glide activity stream (#239, #244) (@roma-glushko) +- ✨ Switched to the new docs (@roma-glushko) +- πŸ”§ #240: Automatically install air (#277, #270) (@ppmdo, @roma-glushko) + +## [0.0.3-rc.2], [0.0.3] (Apr 17, 2024) Final major improvements to streaming chat workflow. Fixed issues with Cohere streaming chat. Expanded and revisited Cohere params in config. @@ -166,7 +210,8 @@ Bringing support for streaming chat in Glide. - πŸ”§ [chores] Automatic coverage reports #39 (@roma-glushko) - πŸ‘· [build] Setup release workflows #9 (@roma-glushko) -[unreleased]: https://github.com/olivierlacan/keep-a-changelog/compare/0.0.3...HEAD +[unreleased]: https://github.com/EinStack/glide/compare/0.1.0-rc.1...HEAD +[0.1.0-rc.1]: https://github.com/EinStack/glide/compare/0.0.3...0.1.0-rc.1 [0.0.3]: https://github.com/EinStack/glide/compare/0.0.3-rc.1..0.0.3 [0.0.3-rc.2]: https://github.com/EinStack/glide/compare/0.0.3-rc.1..0.0.3-rc.2 [0.0.3-rc.1]: https://github.com/EinStack/glide/compare/0.0.2..0.0.3-rc.1 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2735b5e4..34cdff5f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -73,3 +73,24 @@ That's perfectly fine! Feel free to connect with us in [Discord](https://discord.gg/rsBzprY7uT) and ask any question you have. Remember, there are no dumb questions, but there can be missing opportunities to make your life easier if you don't speak up about things you struggle with. + + +## Project Management + +EinStack uses Github functionality to do all sorts of management and planning of Glide functionality: + +- We use Github Projects to manage [the Glide's roadmap](https://github.com/orgs/EinStack/projects/1/views/4) +- We use Github issues to manage epics (e.g. bigger functionality that would not fit one task or pull request) and the corresponding tasks +- Github issue labels to indicate epic priority and other horizontal properties of the functionality like type, area, etc +- Github milestones to assign epics to upcoming releases which may be connected to Glide incremental releases or solve some specific use case (e.g. RAG) + +Glide Project Management + +### How to add a new epic? + +You can do that by: +- creating a new Github issue +- assigning the `type:epic` to it +- adding it to [the Glide Roadmap project](https://github.com/orgs/EinStack/projects/1/views/4) (the backlog status) + +Be sure to let everyone know about this in the EinStack Discord (#general channel is fine). diff --git a/Makefile b/Makefile index 4cebf96b..16e15076 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ CHECKER_BIN=$(PWD)/tmp/bin -VERSION_PACKAGE := glide/pkg +VERSION_PACKAGE := glide/pkg/version COMMIT ?= $(shell git describe --dirty --long --always --abbrev=15) BUILD_DATE ?= $(shell date -u +"%Y-%m-%dT%H:%M:%SZ") VERSION ?= "latest" -LDFLAGS_COMMON := "-s -w -X $(VERSION_PACKAGE).commitSha=$(COMMIT) -X $(VERSION_PACKAGE).version=$(VERSION) -X $(VERSION_PACKAGE).buildDate=$(BUILD_DATE)" +LDFLAGS_COMMON := "-X $(VERSION_PACKAGE).commitSha=$(COMMIT) -X $(VERSION_PACKAGE).Version=$(VERSION) -X $(VERSION_PACKAGE).buildDate=$(BUILD_DATE)" .PHONY: help @@ -13,14 +13,16 @@ help: @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' -install-checkers: ## Install static checkers +$(CHECKER_BIN)/.installed: $(CHECKER_BIN)/.installed ## Install static checkers @echo "🚚 Downloading binaries.." @GOBIN=$(CHECKER_BIN) go install mvdan.cc/gofumpt@latest @GOBIN=$(CHECKER_BIN) go install golang.org/x/vuln/cmd/govulncheck@latest @GOBIN=$(CHECKER_BIN) go install github.com/securego/gosec/v2/cmd/gosec@latest @GOBIN=$(CHECKER_BIN) go install github.com/swaggo/swag/cmd/swag@latest + @GOBIN=$(CHECKER_BIN) go install github.com/air-verse/air@latest + @touch $(CHECKER_BIN)/.installed -lint: install-checkers ## Lint the source code +lint: $(CHECKER_BIN)/.installed ## Lint the source code @echo "🧹 Cleaning go.mod.." @go mod tidy @echo "🧹 Formatting files.." @@ -31,19 +33,34 @@ lint: install-checkers ## Lint the source code @echo "🧹 GoCI Lint.." @golangci-lint run ./... -vuln: install-checkers ## Check for vulnerabilities +vuln: $(CHECKER_BIN)/.installed ## Check for vulnerabilities @echo "πŸ” Checking for vulnerabilities" @#$(CHECKER_BIN)/govulncheck -test ./... enable in https://github.com/EinStack/glide/issues/169 @$(CHECKER_BIN)/gosec -quiet -exclude=G104 ./... -run: ## Run Glide - @go run -ldflags $(LDFLAGS_COMMON) main.go -c ./config.dev.yaml +run: $(CHECKER_BIN)/.installed ## Run Glide + @$(CHECKER_BIN)/air -c .air.toml build: ## Build Glide - @go build -ldflags $(LDFLAGS_COMMON) -o ./dist/glide + @echo "πŸ”¨Building Glide binary.." + @echo "Version: $(VERSION)" + @echo "Commit: $(COMMIT)" + @echo "Build Date: $(BUILD_DATE)" + @go build -ldflags $(LDFLAGS_COMMON) -o ./dist/glide; test: ## Run tests - @go test -v -count=1 -race -shuffle=on -coverprofile=coverage.txt ./... + @go test -v -count=1 -race -shuffle=on -coverprofile=coverage.out ./... -docs-api: install-checkers ## Generate OpenAPI API docs +test-cov: ## Run tests with coverage + @go tool cover -func=coverage.out + +docs-api: $(CHECKER_BIN)/.installed ## Generate OpenAPI API docs @$(CHECKER_BIN)/swag init + +telemetry-up: ## Start observability services needed to receive Glides signals + @docker-compose --profile telemetry up --wait + @echo "Jaeger UI: http://localhost:16686/" + @echo "Grafana UI: http://localhost:3000/" + +telemetry-down: ## Shutdown observability services needed to receive Glides signals + @docker-compose --profile telemetry down diff --git a/README.md b/README.md index 9edbfb14..f1d5e319 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@

Glide: Cloud-Native LLM Gateway for Seamless LLMOps

CodeCov Discord - Glide Docs + Glide Docs License ArtifactHub FOSSA Status @@ -17,19 +17,16 @@ We take all problems of managing and communicating with external providers out o so you can dive into tackling your core challenges. > [!Important] -> Give us a star⭐ to support the project and watchπŸ‘€ our repositories not to miss any update. Appriciate your interest πŸ™ +> Glide is under active development right now πŸ› οΈ +> +> Give us a star⭐ to support the project and watchπŸ‘€ our repositories not to miss any update. Appreciate your interest πŸ™ Glide sits between your application and model providers to seamlessly handle various LLMOps tasks like model failover, caching, key management, etc. -Take a look at the develop branch. - -Check out our [documentation](https://glide.einstack.ai)! - -> [!Warning] -> Glide is under active development right now πŸ› οΈ +Check out our [documentation](https://docs.einstack.ai/glide/)! ## Features @@ -97,7 +94,7 @@ See [API Reference](https://glide.einstack.ai/api-reference/introduction) for mo "role": "user", "content": "Where was it played?" }, - "messageHistory": [ + "message_history": [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Who won the world series in 2020?"}, {"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."} @@ -111,7 +108,7 @@ Finally, Glide comes with OpenAPI documentation that is accessible via http://12 That's it πŸ™Œ -Use [our documentation](https://glide.einstack.ai) to further learn about Glide capabilities and configs. +Use [our documentation](https://docs.einstack.ai/glide/) to further learn about Glide capabilities and configs. --- @@ -220,7 +217,7 @@ To let you work with Glide's API with ease, we are going to provide you with SDK Routers are a core functionality of Glide. Think of routers as a group of models with some predefined logic. For example, the resilience router allows a user to define a set of backup models should the initial model fail. Another example, would be to leverage the least-latency router to make latency sensitive LLM calls in the most efficient manner. -Detailed info on routers can be found [here](https://glide.einstack.ai/essentials/routers). +Detailed info on routers can be found [here](https://docs.einstack.ai/glide/docs/routers). #### Available Routers diff --git a/ROADMAP.md b/ROADMAP.md index 2de24477..6a73bede 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,56 +1,12 @@ -*Updated: Wed, Jan 31st, 2024* +# Glide Roadmap -# Glide - Roadmap +Glide uses a Github project functionality to manage roadmap: -This document describes the current status and the upcoming milestones of the Glide gateway. +- [Glide's roadmap](https://github.com/orgs/EinStack/projects/1/views/4) -## Glide +Please upvote or comment on issues that you would like to be implemented or solved in Glide. +We pay attention to that information during prioritization. -### Milestone Summary +Open [an issue](https://github.com/EinStack/glide/issues) or start [a discussion](https://github.com/EinStack/glide/discussions) if there is a feature, enhancement, or use case +you'd like to see supported in Glide. -| Status | Milestone | Goals | -| :---: | :--- | :---: | -| 🍏 | **Unified Chat API** | 4 / 4 | -| 🍏 | **Fallback Routing Strategy** | 1 / 1 | -| 🍏 | **Priority, Round Robin, Weighted Round Robin, Least Latency** | 4 / 4 | -| 🍏 | **Documentation** | 1 / 1 | -| 🍎 | **Private Preview** | 4.5 / 5 | -| 🍎 | **Streaming Support** | 0 / 4 | -| 🍎 | **Embedding Support** | 0 / 4 | -| 🍎 | **Caching** | 0 / 1 | -| 🍎 | **Public Preview** | 0 / 3 | -| 🍎 | **Python SDK** | 0 / 1 | -| 🍎 | **STT & TTS Model Support** | 0 / 2 | -| 🍎 | **Intelligent Routing** | 0 / 1 | -| 🍎 | **General Availability Routing** | 0 / 1 | - -### Private Preview βœ… ([v0.0.1](https://github.com/EinStack/glide/releases/tag/0.0.1)) - -- Unified LLM Chat REST API -- Support for most popular LLM providers -- Seamless model fallbacking -- Routing Strategies: Priority, Round Robin, Weighted Round Robin, Least Latency - -### Public Preview (In Progress) - -- Unified Embeddings API -- Unified Steaming Chat API -- Observability -- The Exact Caching -- Intelligent Routing (?) - -### General Availability - -- Kubernetes Insallation (Helm Chart) -- Python SDK -- Speech-to-text & Text-to-speech models -- The Semantic Caching - -### Future - -- Cost Management & Budgeting -- Safety & Control Over Inputs & Outputs -- and many more! - -Open [an issue](https://github.com/EinStack/glide/issues) or start [a discussion](https://github.com/EinStack/glide/discussions) -if there is a feature or an enhancement you'd like to see in Glide. diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 00000000..51d70399 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,61 @@ +version: "3.7" +services: + otel-collector: + profiles: + - telemetry + image: otel/opentelemetry-collector-contrib-dev:latest + command: ["--config=/etc/otel-col-config.yaml", "${OTELCOL_ARGS}"] + volumes: + - ./tools/otel-col-config.yaml:/etc/otel-col-config.yaml + ports: + - "1888:1888" # pprof extension + - "8888" # Prometheus metrics exposed by the collector + - "8889:8889" # Prometheus exporter metrics + - "13133:13133" # health_check extension + - "4317:4317" # OTLP gRPC receiver + - "55679" # zpages extension + depends_on: + - jaeger-all-in-one + + jaeger-all-in-one: + profiles: + - telemetry + image: jaegertracing/all-in-one:latest + environment: + - COLLECTOR_OTLP_ENABLED=true + ports: + - "16686:16686" + - "14268" + - "14250:14250" + - "6831:6831" + + victoriametrics: + profiles: + - telemetry + container_name: victoriametrics + image: victoriametrics/victoria-metrics + ports: + - "8428:8428" + - "8089:8089" + - "8089:8089/udp" + - "2003:2003" + - "2003:2003/udp" + - "4242:4242" + command: + - '--storageDataPath=/storage' + - '--graphiteListenAddr=:2003' + - '--opentsdbListenAddr=:4242' + - '--httpListenAddr=:8428' + - '--influxListenAddr=:8089' + restart: always + + grafana: + profiles: + - telemetry + image: grafana/grafana:latest + environment: + - GF_AUTH_ANONYMOUS_ENABLED=true + - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin + - GF_AUTH_DISABLE_LOGIN_FORM=true + ports: + - "3000:3000" diff --git "a/docs/api/Language API/\360\237\222\254 Chat Stream.bru" "b/docs/api/Language API/\360\237\222\254 Chat Stream.bru" deleted file mode 100644 index e544c061..00000000 --- "a/docs/api/Language API/\360\237\222\254 Chat Stream.bru" +++ /dev/null @@ -1,11 +0,0 @@ -meta { - name: πŸ’¬ Chat Stream - type: http - seq: 2 -} - -get { - url: {{base_url}}/language/default/chatStream - body: none - auth: none -} diff --git "a/docs/api/Language API/\360\237\222\254 Chat.bru" "b/docs/api/Language API/\360\237\222\254 Chat.bru" deleted file mode 100644 index 6ea21147..00000000 --- "a/docs/api/Language API/\360\237\222\254 Chat.bru" +++ /dev/null @@ -1,21 +0,0 @@ -meta { - name: πŸ’¬ Chat - type: http - seq: 1 -} - -post { - url: {{base_url}}/language/default/chat/ - body: json - auth: none -} - -body:json { - { - "message": { - "role": "user", - "content": "How are you doing?" - }, - "messageHistory": [] - } -} diff --git "a/docs/api/Language API/\360\237\224\247 Router List.bru" "b/docs/api/Language API/\360\237\224\247 Router List.bru" deleted file mode 100644 index 0545245f..00000000 --- "a/docs/api/Language API/\360\237\224\247 Router List.bru" +++ /dev/null @@ -1,21 +0,0 @@ -meta { - name: πŸ”§ Router List - type: http - seq: 3 -} - -get { - url: {{base_url}}/language/ - body: json - auth: none -} - -body:json { - { - "message": { - "role": "user", - "content": "How are you doing?" - }, - "messageHistory": [] - } -} diff --git a/docs/api/bruno.json b/docs/api/bruno.json deleted file mode 100644 index c543e3e0..00000000 --- a/docs/api/bruno.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "version": "1", - "name": "glide", - "type": "collection" -} \ No newline at end of file diff --git a/docs/api/environments/Development.bru b/docs/api/environments/Development.bru deleted file mode 100644 index a8abb8bf..00000000 --- a/docs/api/environments/Development.bru +++ /dev/null @@ -1,3 +0,0 @@ -vars { - base_url: http://127.0.0.1:9099/v1 -} diff --git "a/docs/api/\360\237\224\247 Health.bru" "b/docs/api/\360\237\224\247 Health.bru" deleted file mode 100644 index df4d4d10..00000000 --- "a/docs/api/\360\237\224\247 Health.bru" +++ /dev/null @@ -1,11 +0,0 @@ -meta { - name: πŸ”§ Health - type: http - seq: 1 -} - -get { - url: {{base_url}}/health/ - body: none - auth: none -} diff --git a/docs/docs.go b/docs/docs.go index 65d48212..51a45f21 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -40,7 +40,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/http.HealthSchema" + "$ref": "#/definitions/schemas.HealthSchema" } } } @@ -48,7 +48,7 @@ const docTemplate = `{ }, "/v1/language/": { "get": { - "description": "Retrieve list of configured language routers and their configurations", + "description": "Retrieve list of configured active language routers and their configurations", "consumes": [ "application/json" ], @@ -64,7 +64,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/http.RouterListSchema" + "$ref": "#/definitions/schemas.RouterListSchema" } } } @@ -112,13 +112,13 @@ const docTemplate = `{ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/http.ErrorSchema" + "$ref": "#/definitions/schemas.Error" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/http.ErrorSchema" + "$ref": "#/definitions/schemas.Error" } } } @@ -179,7 +179,7 @@ const docTemplate = `{ "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/http.ErrorSchema" + "$ref": "#/definitions/schemas.Error" } }, "426": { @@ -190,698 +190,104 @@ const docTemplate = `{ } }, "definitions": { - "anthropic.Config": { + "schemas.ChatMessage": { "type": "object", "required": [ - "apiVersion", - "baseUrl", - "chatEndpoint", - "model" + "content", + "role" ], "properties": { - "apiVersion": { - "type": "string" - }, - "baseUrl": { - "type": "string" - }, - "chatEndpoint": { - "type": "string" - }, - "defaultParams": { - "$ref": "#/definitions/anthropic.Params" - }, - "model": { - "type": "string" - } - } - }, - "anthropic.Params": { - "type": "object", - "properties": { - "max_tokens": { - "type": "integer" - }, - "metadata": { + "content": { + "description": "The content of the message.", "type": "string" }, - "stop": { - "type": "array", - "items": { - "type": "string" - } - }, - "system": { + "role": { + "description": "The role of the author of this message. One of system, user, or assistant.", "type": "string" - }, - "temperature": { - "type": "number" - }, - "top_k": { - "type": "integer" - }, - "top_p": { - "type": "number" } } }, - "azureopenai.Config": { + "schemas.ChatRequest": { "type": "object", "required": [ - "apiVersion", - "baseUrl", - "model" + "message" ], "properties": { - "apiVersion": { - "description": "The API version to use for this operation. This follows the YYYY-MM-DD format (e.g 2023-05-15)", - "type": "string" - }, - "baseUrl": { - "description": "The name of your Azure OpenAI Resource (e.g https://glide-test.openai.azure.com/)", - "type": "string" - }, - "chatEndpoint": { - "type": "string" - }, - "defaultParams": { - "$ref": "#/definitions/azureopenai.Params" - }, - "model": { - "description": "This is your deployment name. You're required to first deploy a model before you can make calls (e.g. glide-gpt-35)", - "type": "string" - } - } - }, - "azureopenai.Params": { - "type": "object", - "properties": { - "frequency_penalty": { - "type": "integer" - }, - "logit_bias": { - "type": "object", - "additionalProperties": { - "type": "number" - } - }, - "max_tokens": { - "type": "integer" - }, - "n": { - "type": "integer" - }, - "presence_penalty": { - "type": "integer" - }, - "response_format": { - "description": "TODO: should this be a part of the chat request API?" - }, - "seed": { - "type": "integer" - }, - "stop": { - "type": "array", - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number" + "message": { + "$ref": "#/definitions/schemas.ChatMessage" }, - "tool_choice": {}, - "tools": { + "message_history": { "type": "array", "items": { - "type": "string" + "$ref": "#/definitions/schemas.ChatMessage" } }, - "top_p": { - "type": "number" - }, - "user": { - "type": "string" - } - } - }, - "bedrock.Config": { - "type": "object", - "required": [ - "awsRegion", - "baseUrl", - "chatEndpoint", - "model" - ], - "properties": { - "awsRegion": { - "type": "string" - }, - "baseUrl": { - "type": "string" - }, - "chatEndpoint": { - "type": "string" - }, - "defaultParams": { - "$ref": "#/definitions/bedrock.Params" - }, - "model": { - "type": "string" - } - } - }, - "bedrock.Params": { - "type": "object", - "properties": { - "max_tokens": { - "type": "integer" - }, - "stop": { - "type": "array", - "items": { - "type": "string" + "override_params": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/schemas.ModelParamsOverride" } - }, - "temperature": { - "type": "number" - }, - "top_p": { - "type": "number" } } }, - "clients.ClientConfig": { - "type": "object", - "properties": { - "timeout": { - "type": "string" - } - } - }, - "cohere.Config": { - "type": "object", - "required": [ - "baseUrl", - "chatEndpoint", - "model" - ], - "properties": { - "baseUrl": { - "type": "string" - }, - "chatEndpoint": { - "type": "string" - }, - "defaultParams": { - "$ref": "#/definitions/cohere.Params" - }, - "model": { - "description": "https://docs.cohere.com/docs/models#command", - "type": "string" - } - } - }, - "cohere.Params": { + "schemas.ChatResponse": { "type": "object", - "required": [ - "temperature" - ], "properties": { - "connectors": { - "type": "array", - "items": { - "type": "string" - } - }, - "frequency_penalty": { - "type": "number", - "maximum": 1, - "minimum": 0 - }, - "k": { - "type": "integer", - "maximum": 500, - "minimum": 0 - }, - "max_tokens": { - "type": "integer" - }, - "p": { - "type": "number", - "maximum": 0.99, - "minimum": 0.01 - }, - "preamble": { - "type": "string" - }, - "presence_penalty": { - "type": "number", - "maximum": 1, - "minimum": 0 - }, - "prompt_truncation": { - "type": "string" - }, - "search_queries_only": { + "cached": { "type": "boolean" }, - "seed": { + "created_at": { "type": "integer" }, - "stop_sequences": { - "type": "array", - "maxItems": 5, - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number" - } - } - }, - "http.ErrorSchema": { - "type": "object", - "properties": { - "message": { - "type": "string" - } - } - }, - "http.HealthSchema": { - "type": "object", - "properties": { - "healthy": { - "type": "boolean" - } - } - }, - "http.RouterListSchema": { - "type": "object", - "properties": { - "routers": { - "type": "array", - "items": { - "$ref": "#/definitions/routers.LangRouterConfig" - } - } - } - }, - "latency.Config": { - "type": "object", - "properties": { - "decay": { - "description": "Weight of new latency measurements", - "type": "number" - }, - "update_interval": { - "description": "How often gateway should probe models with not the lowest response latency", - "type": "string" - }, - "warmup_samples": { - "description": "The number of latency probes required to init moving average", - "type": "integer" - } - } - }, - "octoml.Config": { - "type": "object", - "required": [ - "baseUrl", - "chatEndpoint", - "model" - ], - "properties": { - "baseUrl": { + "id": { "type": "string" }, - "chatEndpoint": { + "model_id": { "type": "string" }, - "defaultParams": { - "$ref": "#/definitions/octoml.Params" - }, - "model": { + "model_name": { "type": "string" - } - } - }, - "octoml.Params": { - "type": "object", - "properties": { - "frequency_penalty": { - "type": "integer" - }, - "max_tokens": { - "type": "integer" - }, - "presence_penalty": { - "type": "integer" - }, - "stop": { - "type": "array", - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number" }, - "top_p": { - "type": "number" - } - } - }, - "ollama.Config": { - "type": "object", - "required": [ - "baseUrl", - "chatEndpoint", - "model" - ], - "properties": { - "baseUrl": { - "type": "string" + "model_response": { + "$ref": "#/definitions/schemas.ModelResponse" }, - "chatEndpoint": { + "provider_id": { "type": "string" }, - "defaultParams": { - "$ref": "#/definitions/ollama.Params" - }, - "model": { + "router_id": { "type": "string" } } }, - "ollama.Params": { + "schemas.Error": { "type": "object", "properties": { - "microstat": { - "type": "integer" - }, - "microstat_eta": { - "type": "number" - }, - "microstat_tau": { - "type": "number" - }, - "num_ctx": { - "type": "integer" - }, - "num_gpu": { - "type": "integer" - }, - "num_gqa": { - "type": "integer" - }, - "num_predict": { - "type": "integer" - }, - "num_thread": { - "type": "integer" - }, - "repeat_last_n": { - "type": "integer" - }, - "seed": { - "type": "integer" - }, - "stop": { - "type": "array", - "items": { - "type": "string" - } - }, - "stream": { - "type": "boolean" - }, - "temperature": { - "type": "number" - }, - "tfs_z": { - "type": "number" - }, - "top_k": { - "type": "integer" - }, - "top_p": { - "type": "number" - } - } - }, - "openai.Config": { - "type": "object", - "required": [ - "baseUrl", - "chatEndpoint", - "model" - ], - "properties": { - "baseUrl": { - "type": "string" - }, - "chatEndpoint": { - "type": "string" - }, - "defaultParams": { - "$ref": "#/definitions/openai.Params" - }, - "model": { + "message": { "type": "string" - } - } - }, - "openai.Params": { - "type": "object", - "properties": { - "frequency_penalty": { - "type": "integer" - }, - "logit_bias": { - "type": "object", - "additionalProperties": { - "type": "number" - } - }, - "max_tokens": { - "type": "integer" - }, - "n": { - "type": "integer" - }, - "presence_penalty": { - "type": "integer" - }, - "response_format": { - "description": "TODO: should this be a part of the chat request API?" }, - "seed": { - "type": "integer" - }, - "stop": { - "type": "array", - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number" - }, - "tool_choice": {}, - "tools": { - "type": "array", - "items": { - "type": "string" - } - }, - "top_p": { - "type": "number" - }, - "user": { + "name": { "type": "string" } } }, - "providers.LangModelConfig": { + "schemas.HealthSchema": { "type": "object", - "required": [ - "enabled", - "id" - ], "properties": { - "anthropic": { - "$ref": "#/definitions/anthropic.Config" - }, - "azureopenai": { - "$ref": "#/definitions/azureopenai.Config" - }, - "bedrock": { - "$ref": "#/definitions/bedrock.Config" - }, - "client": { - "$ref": "#/definitions/clients.ClientConfig" - }, - "cohere": { - "$ref": "#/definitions/cohere.Config" - }, - "enabled": { - "description": "Is the model enabled?", + "healthy": { "type": "boolean" - }, - "error_budget": { - "type": "string" - }, - "id": { - "description": "Model instance ID (unique in scope of the router)", - "type": "string" - }, - "latency": { - "$ref": "#/definitions/latency.Config" - }, - "octoml": { - "$ref": "#/definitions/octoml.Config" - }, - "ollama": { - "$ref": "#/definitions/ollama.Config" - }, - "openai": { - "description": "Add other providers like", - "allOf": [ - { - "$ref": "#/definitions/openai.Config" - } - ] - }, - "weight": { - "type": "integer" - } - } - }, - "retry.ExpRetryConfig": { - "type": "object", - "properties": { - "base_multiplier": { - "type": "integer" - }, - "max_delay": { - "type": "integer" - }, - "max_retries": { - "type": "integer" - }, - "min_delay": { - "type": "integer" } } }, - "routers.LangRouterConfig": { + "schemas.ModelParamsOverride": { "type": "object", - "required": [ - "enabled", - "models", - "retry", - "routers", - "strategy" - ], "properties": { - "enabled": { - "description": "Is router enabled?", - "type": "boolean" - }, - "models": { - "description": "the list of models that could handle requests", - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/definitions/providers.LangModelConfig" - } - }, - "retry": { - "description": "retry when no healthy model is available to router", + "message": { + "description": "TODO: should be just string?", "allOf": [ { - "$ref": "#/definitions/retry.ExpRetryConfig" + "$ref": "#/definitions/schemas.ChatMessage" } ] - }, - "routers": { - "description": "Unique router ID", - "type": "string" - }, - "strategy": { - "description": "strategy on picking the next model to serve the request", - "type": "string" - } - } - }, - "schemas.ChatMessage": { - "type": "object", - "required": [ - "content", - "role" - ], - "properties": { - "content": { - "description": "The content of the message.", - "type": "string" - }, - "name": { - "description": "The name of the author of this message. May contain a-z, A-Z, 0-9, and underscores,\nwith a maximum length of 64 characters.", - "type": "string" - }, - "role": { - "description": "The role of the author of this message. One of system, user, or assistant.", - "type": "string" - } - } - }, - "schemas.ChatRequest": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "$ref": "#/definitions/schemas.ChatMessage" - }, - "messageHistory": { - "type": "array", - "items": { - "$ref": "#/definitions/schemas.ChatMessage" - } - }, - "override": { - "$ref": "#/definitions/schemas.OverrideChatRequest" - } - } - }, - "schemas.ChatResponse": { - "type": "object", - "properties": { - "cached": { - "type": "boolean" - }, - "created": { - "type": "integer" - }, - "id": { - "type": "string" - }, - "model": { - "type": "string" - }, - "modelResponse": { - "$ref": "#/definitions/schemas.ModelResponse" - }, - "model_id": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "router": { - "type": "string" } } }, @@ -891,42 +297,36 @@ const docTemplate = `{ "message": { "$ref": "#/definitions/schemas.ChatMessage" }, - "responseId": { + "metadata": { "type": "object", "additionalProperties": { "type": "string" } }, - "tokenCount": { + "token_usage": { "$ref": "#/definitions/schemas.TokenUsage" } } }, - "schemas.OverrideChatRequest": { + "schemas.RouterListSchema": { "type": "object", - "required": [ - "message", - "model_id" - ], "properties": { - "message": { - "$ref": "#/definitions/schemas.ChatMessage" - }, - "model_id": { - "type": "string" + "routers": { + "type": "array", + "items": {} } } }, "schemas.TokenUsage": { "type": "object", "properties": { - "promptTokens": { + "prompt_tokens": { "type": "integer" }, - "responseTokens": { + "response_tokens": { "type": "integer" }, - "totalTokens": { + "total_tokens": { "type": "integer" } } diff --git a/docs/images/einstack-project-management.excalidraw b/docs/images/einstack-project-management.excalidraw new file mode 100644 index 00000000..71e9c7c9 --- /dev/null +++ b/docs/images/einstack-project-management.excalidraw @@ -0,0 +1,1997 @@ +{ + "type": "excalidraw", + "version": 2, + "source": "https://excalidraw.com", + "elements": [ + { + "id": "ohPPvvJjAjnicfUwo8K4p", + "type": "rectangle", + "x": 1211.070342769188, + "y": -251.6543868522168, + "width": 531.9488463825525, + "height": 293.9574851430459, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#d0bfff", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b0U", + "roundness": null, + "seed": 893668705, + "version": 265, + "versionNonce": 941087233, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "VnQhaVGljqDUQpt8b-kdg" + }, + { + "id": "Ea1MsIv05K4YdCkEmnp9L", + "type": "arrow" + }, + { + "id": "jUkVRGo9k4RNXujtt7YQA", + "type": "arrow" + }, + { + "id": "SxoDd33sDJTKwmeg-ZFe1", + "type": "arrow" + }, + { + "id": "LT1QyDhJfPgP-7SzC4QmQ", + "type": "arrow" + } + ], + "updated": 1714563298968, + "link": null, + "locked": false + }, + { + "id": "VnQhaVGljqDUQpt8b-kdg", + "type": "text", + "x": 1365.2828183286283, + "y": -139.67564428069383, + "width": 223.52389526367188, + "height": 70, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#d0bfff", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b0V", + "roundness": null, + "seed": 584890305, + "version": 223, + "versionNonce": 665102127, + "isDeleted": false, + "boundElements": null, + "updated": 1714563265567, + "link": null, + "locked": false, + "text": "Roadmap\n(Github Project)", + "fontSize": 28, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "ohPPvvJjAjnicfUwo8K4p", + "originalText": "Roadmap\n(Github Project)", + "lineHeight": 1.25 + }, + { + "id": "0dJZm4GcpTSiymfJltyZS", + "type": "rectangle", + "x": 620.532470703125, + "y": 376.8847351074219, + "width": 156.4697265625, + "height": 112.94268798828125, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b0W", + "roundness": null, + "seed": 871037729, + "version": 243, + "versionNonce": 1068492047, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "udPISMHDmSObtnLMaL11T" + }, + { + "id": "Ea1MsIv05K4YdCkEmnp9L", + "type": "arrow" + }, + { + "id": "OeUzHlVvyVtiwsDvKswXA", + "type": "arrow" + }, + { + "id": "iwP7UbZ59GYJ--HaL9fHp", + "type": "arrow" + } + ], + "updated": 1714563085436, + "link": null, + "locked": false + }, + { + "id": "udPISMHDmSObtnLMaL11T", + "type": "text", + "x": 647.1993637084961, + "y": 413.3560791015625, + "width": 103.13594055175781, + "height": 40, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b0X", + "roundness": null, + "seed": 1761548129, + "version": 205, + "versionNonce": 229534511, + "isDeleted": false, + "boundElements": null, + "updated": 1714563085436, + "link": null, + "locked": false, + "text": "Epic (Github \nissue)", + "fontSize": 16, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "0dJZm4GcpTSiymfJltyZS", + "originalText": "Epic (Github issue)", + "lineHeight": 1.25 + }, + { + "id": "BgdU6NSajlIROqMitkKiR", + "type": "text", + "x": 387.4367370605469, + "y": 409.6357727050781, + "width": 211.58384704589844, + "height": 40, + "angle": 0, + "strokeColor": "#868e96", + "backgroundColor": "#b2f2bb", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b0Y", + "roundness": null, + "seed": 1194010287, + "version": 408, + "versionNonce": 501746625, + "isDeleted": false, + "boundElements": [], + "updated": 1714563140434, + "link": null, + "locked": false, + "text": "epic has \ntype:epic & priority:* labels", + "fontSize": 16, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "epic has \ntype:epic & priority:* labels", + "lineHeight": 1.25 + }, + { + "id": "Ea1MsIv05K4YdCkEmnp9L", + "type": "arrow", + "x": 1483.7390736245284, + "y": 42.80380446880204, + "width": 775.1972143874498, + "height": 332.4618523907802, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b0a", + "roundness": null, + "seed": 660818401, + "version": 742, + "versionNonce": 1793579425, + "isDeleted": false, + "boundElements": null, + "updated": 1714563336234, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -775.1972143874498, + 332.4618523907802 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "ohPPvvJjAjnicfUwo8K4p", + "focus": -0.5759489815189567, + "gap": 1 + }, + "endBinding": { + "elementId": "0dJZm4GcpTSiymfJltyZS", + "focus": -0.5987097089613762, + "gap": 1.6190782478396386 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "OeUzHlVvyVtiwsDvKswXA", + "type": "arrow", + "x": 684.7953626658173, + "y": 491.5003967285156, + "width": 148.3854830385344, + "height": 82.96932983398438, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b0b", + "roundness": null, + "seed": 785730145, + "version": 498, + "versionNonce": 591589167, + "isDeleted": false, + "boundElements": null, + "updated": 1714563090762, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -148.3854830385344, + 82.96932983398438 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "0dJZm4GcpTSiymfJltyZS", + "focus": -0.5022337091469952, + "gap": 1.6729736328125 + }, + "endBinding": { + "elementId": "IoMlhxX9iCNuQ9nSfbfjW", + "focus": -0.48156380520885866, + "gap": 2.5262451171875 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "IoMlhxX9iCNuQ9nSfbfjW", + "type": "rectangle", + "x": 457.7303466796875, + "y": 576.9959716796875, + "width": 150.1580810546875, + "height": 76.00982666015624, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e9ecef", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b0c", + "roundness": null, + "seed": 421950287, + "version": 135, + "versionNonce": 1369171727, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "TEcvl_P3h7_EMaZVTq5oI" + }, + { + "id": "OeUzHlVvyVtiwsDvKswXA", + "type": "arrow" + } + ], + "updated": 1714563050067, + "link": null, + "locked": false + }, + { + "id": "TEcvl_P3h7_EMaZVTq5oI", + "type": "text", + "x": 471.99342346191406, + "y": 595.0008850097656, + "width": 121.63192749023438, + "height": 40, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b0d", + "roundness": null, + "seed": 245214721, + "version": 131, + "versionNonce": 1187654959, + "isDeleted": false, + "boundElements": null, + "updated": 1714563050067, + "link": null, + "locked": false, + "text": "Tasks (Github \nissue)", + "fontSize": 16, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "IoMlhxX9iCNuQ9nSfbfjW", + "originalText": "Tasks (Github issue)", + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 202, + "versionNonce": 1328751297, + "index": "b0e", + "isDeleted": false, + "id": "F68zJdw0ts4DyawPBbAgt", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 713.8971557617188, + "y": 573.8642883300781, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e9ecef", + "width": 150.1580810546875, + "height": 76.00982666015624, + "seed": 1839634625, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "type": "text", + "id": "Iwe5PsZ56jqWrrj92rxW-" + }, + { + "id": "iwP7UbZ59GYJ--HaL9fHp", + "type": "arrow" + } + ], + "updated": 1714563059195, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 197, + "versionNonce": 158910625, + "index": "b0f", + "isDeleted": false, + "id": "Iwe5PsZ56jqWrrj92rxW-", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 728.1602325439453, + "y": 591.8692016601562, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 121.63192749023438, + "height": 40, + "seed": 1639438497, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563054528, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "Tasks (Github \nissue)", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "F68zJdw0ts4DyawPBbAgt", + "originalText": "Tasks (Github issue)", + "lineHeight": 1.25 + }, + { + "id": "iwP7UbZ59GYJ--HaL9fHp", + "type": "arrow", + "x": 699.6708305336042, + "y": 491.5767517089844, + "width": 105.82189607373562, + "height": 80.00460815429688, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e9ecef", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b0g", + "roundness": null, + "seed": 142988385, + "version": 276, + "versionNonce": 1239308417, + "isDeleted": false, + "boundElements": null, + "updated": 1714563092628, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 105.82189607373562, + 80.00460815429688 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "0dJZm4GcpTSiymfJltyZS", + "focus": 0.4976470019019677, + "gap": 1.74932861328125 + }, + "endBinding": { + "elementId": "F68zJdw0ts4DyawPBbAgt", + "focus": 0.556890683861238, + "gap": 2.282928466796875 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "yjQGCW7khh1GFOEdhIsuH", + "type": "text", + "x": 663.6615600585938, + "y": 601.82080078125, + "width": 13.151962280273438, + "height": 20, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e9ecef", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b0h", + "roundness": null, + "seed": 2081330159, + "version": 40, + "versionNonce": 697667969, + "isDeleted": false, + "boundElements": null, + "updated": 1714563068028, + "link": null, + "locked": false, + "text": "...", + "fontSize": 16, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "...", + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 409, + "versionNonce": 164406159, + "index": "b0i", + "isDeleted": false, + "id": "UP0fObixyTidTVBgA0rxp", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1086.909312664645, + "y": 373.60133361816406, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 156.4697265625, + "height": 112.94268798828125, + "seed": 1158951951, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "type": "text", + "id": "6iIFjJHdyxnQ6eEf6rtBq" + }, + { + "id": "UNP0lHDKUlPU8o5fEVSYX", + "type": "arrow" + }, + { + "id": "bymdQQtcH_xLIQFZi2iDG", + "type": "arrow" + }, + { + "id": "jUkVRGo9k4RNXujtt7YQA", + "type": "arrow" + } + ], + "updated": 1714563269235, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 373, + "versionNonce": 581917103, + "index": "b0j", + "isDeleted": false, + "id": "6iIFjJHdyxnQ6eEf6rtBq", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1150.0401872984341, + "y": 420.0726776123047, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 30.207977294921875, + "height": 20, + "seed": 531683887, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563269235, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "Epic", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "UP0fObixyTidTVBgA0rxp", + "originalText": "Epic", + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 989, + "versionNonce": 1702383, + "index": "b0l", + "isDeleted": false, + "id": "UNP0lHDKUlPU8o5fEVSYX", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1151.2308089005762, + "y": 488.2169952392578, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 148.2315789556069, + "height": 82.96932983398438, + "seed": 34953839, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563269235, + "link": null, + "locked": false, + "startBinding": { + "elementId": "UP0fObixyTidTVBgA0rxp", + "focus": -0.5022337091469952, + "gap": 1.6729736328125 + }, + "endBinding": { + "elementId": "u3_SIGwtcY_DEbCwoKZlM", + "focus": -0.48156380520885866, + "gap": 2.5262451171875 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + -148.2315789556069, + 82.96932983398438 + ] + ] + }, + { + "type": "rectangle", + "version": 296, + "versionNonce": 58908303, + "index": "b0m", + "isDeleted": false, + "id": "u3_SIGwtcY_DEbCwoKZlM", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 924.3609313964844, + "y": 573.7125701904297, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e9ecef", + "width": 150.1580810546875, + "height": 76.00982666015624, + "seed": 1115567247, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "type": "text", + "id": "fvBSY0gMvSEmAFUjox6Z2" + }, + { + "id": "UNP0lHDKUlPU8o5fEVSYX", + "type": "arrow" + } + ], + "updated": 1714563153864, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 292, + "versionNonce": 535180463, + "index": "b0n", + "isDeleted": false, + "id": "fvBSY0gMvSEmAFUjox6Z2", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 938.6240081787109, + "y": 591.7174835205078, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 121.63192749023438, + "height": 40, + "seed": 1359399599, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563153864, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "Tasks (Github \nissue)", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "u3_SIGwtcY_DEbCwoKZlM", + "originalText": "Tasks (Github issue)", + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 363, + "versionNonce": 1536562415, + "index": "b0o", + "isDeleted": false, + "id": "g92O3UGpGks611cVAkqWI", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1180.5277404785156, + "y": 570.5808868408203, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e9ecef", + "width": 150.1580810546875, + "height": 76.00982666015624, + "seed": 1247255759, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "type": "text", + "id": "cSOzoG9tbBCj3lAO1yYUT" + }, + { + "id": "bymdQQtcH_xLIQFZi2iDG", + "type": "arrow" + } + ], + "updated": 1714563153864, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 358, + "versionNonce": 1359191823, + "index": "b0p", + "isDeleted": false, + "id": "cSOzoG9tbBCj3lAO1yYUT", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1194.7908172607422, + "y": 588.5858001708984, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 121.63192749023438, + "height": 40, + "seed": 571026159, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563153864, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "Tasks (Github \nissue)", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "g92O3UGpGks611cVAkqWI", + "originalText": "Tasks (Github issue)", + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 767, + "versionNonce": 386501167, + "index": "b0q", + "isDeleted": false, + "id": "bymdQQtcH_xLIQFZi2iDG", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1166.1092237214302, + "y": 488.29335021972656, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e9ecef", + "width": 105.97701096030323, + "height": 80.00460815429688, + "seed": 1151595791, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563269235, + "link": null, + "locked": false, + "startBinding": { + "elementId": "UP0fObixyTidTVBgA0rxp", + "focus": 0.4976470019019677, + "gap": 1.74932861328125 + }, + "endBinding": { + "elementId": "g92O3UGpGks611cVAkqWI", + "focus": 0.556890683861238, + "gap": 2.282928466796875 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 105.97701096030323, + 80.00460815429688 + ] + ] + }, + { + "type": "text", + "version": 201, + "versionNonce": 1780000111, + "index": "b0r", + "isDeleted": false, + "id": "hhhsLLjMeXiJC_Cx68J1T", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1130.2921447753906, + "y": 598.5373992919922, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e9ecef", + "width": 13.151962280273438, + "height": 20, + "seed": 2040560431, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563153864, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "...", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "...", + "lineHeight": 1.25 + }, + { + "id": "jUkVRGo9k4RNXujtt7YQA", + "type": "arrow", + "x": 1486.7003602450206, + "y": 43.174554101615314, + "width": 313.6944208871398, + "height": 326.33309351486605, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e9ecef", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b0s", + "roundness": null, + "seed": 41105249, + "version": 766, + "versionNonce": 147987279, + "isDeleted": false, + "boundElements": null, + "updated": 1714563333733, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -313.6944208871398, + 326.33309351486605 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "ohPPvvJjAjnicfUwo8K4p", + "focus": -0.3726841839493154, + "gap": 1 + }, + "endBinding": { + "elementId": "UP0fObixyTidTVBgA0rxp", + "focus": -0.38000272037128885, + "gap": 4.093686001682727 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "0dardDR8WMOQDvDV--lO3", + "type": "rectangle", + "x": 346.48131013680995, + "y": 331.5592320978625, + "width": 1080.951416015625, + "height": 374.5418395996094, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b0t", + "roundness": null, + "seed": 661620271, + "version": 153, + "versionNonce": 2088365391, + "isDeleted": false, + "boundElements": null, + "updated": 1714563270968, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 304, + "versionNonce": 673455663, + "index": "b0u", + "isDeleted": false, + "id": "svjoH6HImMD3BDuJ86RF1", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1769.9696582153044, + "y": 376.6456348664975, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 156.4697265625, + "height": 112.94268798828125, + "seed": 2113666831, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "type": "text", + "id": "XvTM3Tm2yf5b4UapVaJfA" + }, + { + "id": "9I6dkfVg-tmDC_HTlzIzD", + "type": "arrow" + }, + { + "id": "ZMwJFfgkbRlB0SwED-2U-", + "type": "arrow" + }, + { + "id": "SxoDd33sDJTKwmeg-ZFe1", + "type": "arrow" + } + ], + "updated": 1714563287399, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 274, + "versionNonce": 476942159, + "index": "b0v", + "isDeleted": false, + "id": "XvTM3Tm2yf5b4UapVaJfA", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1833.1005328490935, + "y": 423.11697886063814, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 30.207977294921875, + "height": 20, + "seed": 526861615, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563211232, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "Epic", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "svjoH6HImMD3BDuJ86RF1", + "originalText": "Epic", + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 672, + "versionNonce": 1219292623, + "index": "b0x", + "isDeleted": false, + "id": "9I6dkfVg-tmDC_HTlzIzD", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1834.2796977634962, + "y": 491.26129648759127, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 148.4635537112531, + "height": 83.07760267025367, + "seed": 1366099311, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563208369, + "link": null, + "locked": false, + "startBinding": { + "elementId": "svjoH6HImMD3BDuJ86RF1", + "focus": -0.5022337091469952, + "gap": 1.6729736328125 + }, + "endBinding": { + "elementId": "x2XdAZKah5xXQisHtA6xd", + "focus": -0.48156380520885866, + "gap": 2.5262451171875 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + -148.4635537112531, + 83.07760267025367 + ] + ] + }, + { + "type": "rectangle", + "version": 193, + "versionNonce": 69506735, + "index": "b0y", + "isDeleted": false, + "id": "x2XdAZKah5xXQisHtA6xd", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1607.167534191867, + "y": 576.8651442750324, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e9ecef", + "width": 150.1580810546875, + "height": 76.00982666015624, + "seed": 1068007311, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "type": "text", + "id": "IirKkPKImJHscp2l7msA9" + }, + { + "id": "9I6dkfVg-tmDC_HTlzIzD", + "type": "arrow" + } + ], + "updated": 1714563205604, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 192, + "versionNonce": 589550959, + "index": "b0z", + "isDeleted": false, + "id": "IirKkPKImJHscp2l7msA9", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1657.8945926025115, + "y": 604.8700576051106, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 48.70396423339844, + "height": 20, + "seed": 1756345775, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563233428, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "Tasks", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "x2XdAZKah5xXQisHtA6xd", + "originalText": "Tasks", + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 263, + "versionNonce": 1942462401, + "index": "b10", + "isDeleted": false, + "id": "pfPLa2lTvFhoB3NTOMXWi", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1863.3886726229598, + "y": 573.5865247313699, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e9ecef", + "width": 150.1580810546875, + "height": 76.00982666015624, + "seed": 1940596687, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "type": "text", + "id": "t4NPWmIUFr5wUKfCPrPdf" + }, + { + "id": "ZMwJFfgkbRlB0SwED-2U-", + "type": "arrow" + } + ], + "updated": 1714563234879, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 261, + "versionNonce": 32379617, + "index": "b11", + "isDeleted": false, + "id": "t4NPWmIUFr5wUKfCPrPdf", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1914.1157310336043, + "y": 601.591438061448, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 48.70396423339844, + "height": 20, + "seed": 246633967, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563237657, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "Tasks", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "pfPLa2lTvFhoB3NTOMXWi", + "originalText": "Tasks", + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 456, + "versionNonce": 906709857, + "index": "b12", + "isDeleted": false, + "id": "ZMwJFfgkbRlB0SwED-2U-", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1849.114241426676, + "y": 491.33765146806, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e9ecef", + "width": 105.85084854245997, + "height": 79.96594479651299, + "seed": 282116111, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563234879, + "link": null, + "locked": false, + "startBinding": { + "elementId": "svjoH6HImMD3BDuJ86RF1", + "focus": 0.4976470019019675, + "gap": 1.74932861328125 + }, + "endBinding": { + "elementId": "pfPLa2lTvFhoB3NTOMXWi", + "focus": 0.556890683861238, + "gap": 2.282928466796875 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 105.85084854245997, + 79.96594479651299 + ] + ] + }, + { + "type": "text", + "version": 98, + "versionNonce": 1887486351, + "index": "b13", + "isDeleted": false, + "id": "5l_oCPZR8FXKAJxrhyIZc", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1813.0987475707732, + "y": 601.6899733765949, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e9ecef", + "width": 13.151962280273438, + "height": 20, + "seed": 1543235119, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563205604, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "...", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "...", + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 470, + "versionNonce": 2128088513, + "index": "b14", + "isDeleted": false, + "id": "qWQ0zHVpIpsRbzyDYLf7X", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2235.587124047894, + "y": 373.0882714608066, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 156.4697265625, + "height": 112.94268798828125, + "seed": 2132625487, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "type": "text", + "id": "j0ioBJmhOgq9_AojDq4y_" + }, + { + "id": "y1OPnKxFhP7eqFeXLyVaE", + "type": "arrow" + }, + { + "id": "3BmukIHATsjeZ2hs0o3OA", + "type": "arrow" + }, + { + "id": "LT1QyDhJfPgP-7SzC4QmQ", + "type": "arrow" + } + ], + "updated": 1714563298968, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 433, + "versionNonce": 2113042977, + "index": "b15", + "isDeleted": false, + "id": "j0ioBJmhOgq9_AojDq4y_", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2298.717998681683, + "y": 419.5596154549472, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 30.207977294921875, + "height": 20, + "seed": 403531375, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563223774, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "Epic", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "qWQ0zHVpIpsRbzyDYLf7X", + "originalText": "Epic", + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 1169, + "versionNonce": 658463087, + "index": "b16", + "isDeleted": false, + "id": "y1OPnKxFhP7eqFeXLyVaE", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2300.207950502694, + "y": 487.70393308190035, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 148.11269649389124, + "height": 83.35156458668678, + "seed": 1972682895, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563241207, + "link": null, + "locked": false, + "startBinding": { + "elementId": "qWQ0zHVpIpsRbzyDYLf7X", + "focus": -0.5022337091469952, + "gap": 1.6729736328125 + }, + "endBinding": { + "elementId": "NyLreZSIO4tU1FIUM1g5Q", + "focus": -0.48156380520885866, + "gap": 2.5262451171875 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + -148.11269649389124, + 83.35156458668678 + ] + ] + }, + { + "type": "rectangle", + "version": 357, + "versionNonce": 1877857039, + "index": "b17", + "isDeleted": false, + "id": "NyLreZSIO4tU1FIUM1g5Q", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2073.6707844968005, + "y": 573.5817427857746, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e9ecef", + "width": 150.1580810546875, + "height": 76.00982666015624, + "seed": 2037110447, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "type": "text", + "id": "bISvxUhVSmp-Ebjn9TiOs" + }, + { + "id": "y1OPnKxFhP7eqFeXLyVaE", + "type": "arrow" + } + ], + "updated": 1714563241207, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 356, + "versionNonce": 1320921583, + "index": "b18", + "isDeleted": false, + "id": "bISvxUhVSmp-Ebjn9TiOs", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2124.397842907445, + "y": 601.5866561158527, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 48.70396423339844, + "height": 20, + "seed": 976955599, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563243765, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "Tasks", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "NyLreZSIO4tU1FIUM1g5Q", + "originalText": "Tasks", + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 423, + "versionNonce": 1948592815, + "index": "b19", + "isDeleted": false, + "id": "dEmU6fFrn5e_fawXpMsIp", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2329.270376653259, + "y": 569.8760513419595, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e9ecef", + "width": 150.1580810546875, + "height": 76.00982666015624, + "seed": 1704670959, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "type": "text", + "id": "9M4CB5ea3qXuPncB--iOV" + }, + { + "id": "3BmukIHATsjeZ2hs0o3OA", + "type": "arrow" + } + ], + "updated": 1714563245534, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 421, + "versionNonce": 380622223, + "index": "b1A", + "isDeleted": false, + "id": "9M4CB5ea3qXuPncB--iOV", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2379.9974350639036, + "y": 597.8809646720376, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 48.70396423339844, + "height": 20, + "seed": 1645510927, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563248288, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "Tasks", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "dEmU6fFrn5e_fawXpMsIp", + "originalText": "Tasks", + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 945, + "versionNonce": 1272861967, + "index": "b1B", + "isDeleted": false, + "id": "3BmukIHATsjeZ2hs0o3OA", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2314.8472373777076, + "y": 487.7802880623691, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e9ecef", + "width": 105.93163880217617, + "height": 79.81283481279354, + "seed": 824149807, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563245535, + "link": null, + "locked": false, + "startBinding": { + "elementId": "qWQ0zHVpIpsRbzyDYLf7X", + "focus": 0.4976470019019683, + "gap": 1.74932861328125 + }, + "endBinding": { + "elementId": "dEmU6fFrn5e_fawXpMsIp", + "focus": 0.5568906838612402, + "gap": 2.282928466796875 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 105.93163880217617, + 79.81283481279354 + ] + ] + }, + { + "type": "text", + "version": 259, + "versionNonce": 132942127, + "index": "b1C", + "isDeleted": false, + "id": "ZsoRjhJrqN1vx1T9xszkv", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2279.7293322875703, + "y": 598.4065718873371, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e9ecef", + "width": 13.151962280273438, + "height": 20, + "seed": 287623503, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563205604, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "...", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "...", + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 206, + "versionNonce": 1258392399, + "index": "b1D", + "isDeleted": false, + "id": "7KXyGuZOKE_1kVa8dvg8d", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1496.1622851684294, + "y": 331.12164451917306, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 1080.951416015625, + "height": 374.5418395996094, + "seed": 1602013039, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563205604, + "link": null, + "locked": false + }, + { + "id": "SxoDd33sDJTKwmeg-ZFe1", + "type": "arrow", + "x": 1487.9152131035396, + "y": 44.510420124139046, + "width": 355.38073371419114, + "height": 331.475428102563, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1E", + "roundness": null, + "seed": 1781750223, + "version": 100, + "versionNonce": 347529583, + "isDeleted": false, + "boundElements": null, + "updated": 1714563339267, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 355.38073371419114, + 331.475428102563 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "ohPPvvJjAjnicfUwo8K4p", + "focus": 0.35196212466076976, + "gap": 2.207321833309919 + }, + "endBinding": { + "elementId": "svjoH6HImMD3BDuJ86RF1", + "focus": 0.40598947149776793, + "gap": 1 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "LT1QyDhJfPgP-7SzC4QmQ", + "type": "arrow", + "x": 1489.0843154662116, + "y": 40.96917066017102, + "width": 830.7772047108197, + "height": 330.73258567135906, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1F", + "roundness": null, + "seed": 871251521, + "version": 107, + "versionNonce": 236794849, + "isDeleted": false, + "boundElements": null, + "updated": 1714563342301, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 830.7772047108197, + 330.73258567135906 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "ohPPvvJjAjnicfUwo8K4p", + "focus": 0.5570279009208702, + "gap": 1 + }, + "endBinding": { + "elementId": "qWQ0zHVpIpsRbzyDYLf7X", + "focus": 0.6877938330400006, + "gap": 1.3865151292765177 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "qIZ0SK26phmxOugc5poQ5", + "type": "text", + "x": 1292.7864968402982, + "y": 351.4713543773397, + "width": 106.17596435546875, + "height": 35, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1G", + "roundness": null, + "seed": 1384806753, + "version": 20, + "versionNonce": 1259660897, + "isDeleted": false, + "boundElements": null, + "updated": 1714563317134, + "link": null, + "locked": false, + "text": "Release", + "fontSize": 28, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Release", + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 73, + "versionNonce": 833516751, + "index": "b1H", + "isDeleted": false, + "id": "nZtBVRC8HQ21uAaFRjAdb", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2457.2814891194575, + "y": 346.2250792362137, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 106.17596435546875, + "height": 35, + "seed": 814055969, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1714563320901, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "Release", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Release", + "lineHeight": 1.25 + }, + { + "id": "vPcaqiuzy5GvdmkBUfF_c", + "type": "text", + "x": 810.6365799388013, + "y": 415.3563744707627, + "width": 158.60791015625, + "height": 40, + "angle": 0, + "strokeColor": "#868e96", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1I", + "roundness": null, + "seed": 1757452015, + "version": 174, + "versionNonce": 1765355841, + "isDeleted": false, + "boundElements": null, + "updated": 1714563398834, + "link": null, + "locked": false, + "text": "Each task is linked \nin epic descr", + "fontSize": 16, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Each task is linked \nin epic descr", + "lineHeight": 1.25 + }, + { + "id": "E3koGFppTSx4QXP6QfVAn", + "type": "text", + "x": 914.5357876468717, + "y": -185.36337885218904, + "width": 272.4638366699219, + "height": 120, + "angle": 0, + "strokeColor": "#868e96", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1K", + "roundness": null, + "seed": 494919279, + "version": 200, + "versionNonce": 237353007, + "isDeleted": false, + "boundElements": null, + "updated": 1714563486969, + "link": null, + "locked": false, + "text": "Each epic has status on roadmap:\n- backlog\n- proposal creation\n- implementation\n- delivered\n- on hold", + "fontSize": 16, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Each epic has status on roadmap:\n- backlog\n- proposal creation\n- implementation\n- delivered\n- on hold", + "lineHeight": 1.25 + } + ], + "appState": { + "gridSize": null, + "viewBackgroundColor": "#ffffff" + }, + "files": {} +} \ No newline at end of file diff --git a/docs/images/einstack-project-management.png b/docs/images/einstack-project-management.png new file mode 100644 index 0000000000000000000000000000000000000000..2ebffb8b8af21f5a9d1b4e098f00c6f467747b69 GIT binary patch literal 585692 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%0D-zFwOy{jdx1T12ghQJv6WozebI! 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ⅅYOU_1l*uf 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≪s9f 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 AR{#J2 literal 0 HcmV?d00001 diff --git a/docs/swagger.json b/docs/swagger.json index 1588b4a5..aa0d3b25 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -37,7 +37,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/http.HealthSchema" + "$ref": "#/definitions/schemas.HealthSchema" } } } @@ -45,7 +45,7 @@ }, "/v1/language/": { "get": { - "description": "Retrieve list of configured language routers and their configurations", + "description": "Retrieve list of configured active language routers and their configurations", "consumes": [ "application/json" ], @@ -61,7 +61,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/http.RouterListSchema" + "$ref": "#/definitions/schemas.RouterListSchema" } } } @@ -109,13 +109,13 @@ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/http.ErrorSchema" + "$ref": "#/definitions/schemas.Error" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/http.ErrorSchema" + "$ref": "#/definitions/schemas.Error" } } } @@ -176,7 +176,7 @@ "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/http.ErrorSchema" + "$ref": "#/definitions/schemas.Error" } }, "426": { @@ -187,698 +187,104 @@ } }, "definitions": { - "anthropic.Config": { + "schemas.ChatMessage": { "type": "object", "required": [ - "apiVersion", - "baseUrl", - "chatEndpoint", - "model" + "content", + "role" ], "properties": { - "apiVersion": { - "type": "string" - }, - "baseUrl": { - "type": "string" - }, - "chatEndpoint": { - "type": "string" - }, - "defaultParams": { - "$ref": "#/definitions/anthropic.Params" - }, - "model": { - "type": "string" - } - } - }, - "anthropic.Params": { - "type": "object", - "properties": { - "max_tokens": { - "type": "integer" - }, - "metadata": { + "content": { + "description": "The content of the message.", "type": "string" }, - "stop": { - "type": "array", - "items": { - "type": "string" - } - }, - "system": { + "role": { + "description": "The role of the author of this message. One of system, user, or assistant.", "type": "string" - }, - "temperature": { - "type": "number" - }, - "top_k": { - "type": "integer" - }, - "top_p": { - "type": "number" } } }, - "azureopenai.Config": { + "schemas.ChatRequest": { "type": "object", "required": [ - "apiVersion", - "baseUrl", - "model" + "message" ], "properties": { - "apiVersion": { - "description": "The API version to use for this operation. This follows the YYYY-MM-DD format (e.g 2023-05-15)", - "type": "string" - }, - "baseUrl": { - "description": "The name of your Azure OpenAI Resource (e.g https://glide-test.openai.azure.com/)", - "type": "string" - }, - "chatEndpoint": { - "type": "string" - }, - "defaultParams": { - "$ref": "#/definitions/azureopenai.Params" - }, - "model": { - "description": "This is your deployment name. You're required to first deploy a model before you can make calls (e.g. glide-gpt-35)", - "type": "string" - } - } - }, - "azureopenai.Params": { - "type": "object", - "properties": { - "frequency_penalty": { - "type": "integer" - }, - "logit_bias": { - "type": "object", - "additionalProperties": { - "type": "number" - } - }, - "max_tokens": { - "type": "integer" - }, - "n": { - "type": "integer" - }, - "presence_penalty": { - "type": "integer" - }, - "response_format": { - "description": "TODO: should this be a part of the chat request API?" - }, - "seed": { - "type": "integer" - }, - "stop": { - "type": "array", - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number" + "message": { + "$ref": "#/definitions/schemas.ChatMessage" }, - "tool_choice": {}, - "tools": { + "message_history": { "type": "array", "items": { - "type": "string" + "$ref": "#/definitions/schemas.ChatMessage" } }, - "top_p": { - "type": "number" - }, - "user": { - "type": "string" - } - } - }, - "bedrock.Config": { - "type": "object", - "required": [ - "awsRegion", - "baseUrl", - "chatEndpoint", - "model" - ], - "properties": { - "awsRegion": { - "type": "string" - }, - "baseUrl": { - "type": "string" - }, - "chatEndpoint": { - "type": "string" - }, - "defaultParams": { - "$ref": "#/definitions/bedrock.Params" - }, - "model": { - "type": "string" - } - } - }, - "bedrock.Params": { - "type": "object", - "properties": { - "max_tokens": { - "type": "integer" - }, - "stop": { - "type": "array", - "items": { - "type": "string" + "override_params": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/schemas.ModelParamsOverride" } - }, - "temperature": { - "type": "number" - }, - "top_p": { - "type": "number" } } }, - "clients.ClientConfig": { - "type": "object", - "properties": { - "timeout": { - "type": "string" - } - } - }, - "cohere.Config": { - "type": "object", - "required": [ - "baseUrl", - "chatEndpoint", - "model" - ], - "properties": { - "baseUrl": { - "type": "string" - }, - "chatEndpoint": { - "type": "string" - }, - "defaultParams": { - "$ref": "#/definitions/cohere.Params" - }, - "model": { - "description": "https://docs.cohere.com/docs/models#command", - "type": "string" - } - } - }, - "cohere.Params": { + "schemas.ChatResponse": { "type": "object", - "required": [ - "temperature" - ], "properties": { - "connectors": { - "type": "array", - "items": { - "type": "string" - } - }, - "frequency_penalty": { - "type": "number", - "maximum": 1, - "minimum": 0 - }, - "k": { - "type": "integer", - "maximum": 500, - "minimum": 0 - }, - "max_tokens": { - "type": "integer" - }, - "p": { - "type": "number", - "maximum": 0.99, - "minimum": 0.01 - }, - "preamble": { - "type": "string" - }, - "presence_penalty": { - "type": "number", - "maximum": 1, - "minimum": 0 - }, - "prompt_truncation": { - "type": "string" - }, - "search_queries_only": { + "cached": { "type": "boolean" }, - "seed": { + "created_at": { "type": "integer" }, - "stop_sequences": { - "type": "array", - "maxItems": 5, - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number" - } - } - }, - "http.ErrorSchema": { - "type": "object", - "properties": { - "message": { - "type": "string" - } - } - }, - "http.HealthSchema": { - "type": "object", - "properties": { - "healthy": { - "type": "boolean" - } - } - }, - "http.RouterListSchema": { - "type": "object", - "properties": { - "routers": { - "type": "array", - "items": { - "$ref": "#/definitions/routers.LangRouterConfig" - } - } - } - }, - "latency.Config": { - "type": "object", - "properties": { - "decay": { - "description": "Weight of new latency measurements", - "type": "number" - }, - "update_interval": { - "description": "How often gateway should probe models with not the lowest response latency", - "type": "string" - }, - "warmup_samples": { - "description": "The number of latency probes required to init moving average", - "type": "integer" - } - } - }, - "octoml.Config": { - "type": "object", - "required": [ - "baseUrl", - "chatEndpoint", - "model" - ], - "properties": { - "baseUrl": { + "id": { "type": "string" }, - "chatEndpoint": { + "model_id": { "type": "string" }, - "defaultParams": { - "$ref": "#/definitions/octoml.Params" - }, - "model": { + "model_name": { "type": "string" - } - } - }, - "octoml.Params": { - "type": "object", - "properties": { - "frequency_penalty": { - "type": "integer" - }, - "max_tokens": { - "type": "integer" - }, - "presence_penalty": { - "type": "integer" - }, - "stop": { - "type": "array", - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number" }, - "top_p": { - "type": "number" - } - } - }, - "ollama.Config": { - "type": "object", - "required": [ - "baseUrl", - "chatEndpoint", - "model" - ], - "properties": { - "baseUrl": { - "type": "string" + "model_response": { + "$ref": "#/definitions/schemas.ModelResponse" }, - "chatEndpoint": { + "provider_id": { "type": "string" }, - "defaultParams": { - "$ref": "#/definitions/ollama.Params" - }, - "model": { + "router_id": { "type": "string" } } }, - "ollama.Params": { + "schemas.Error": { "type": "object", "properties": { - "microstat": { - "type": "integer" - }, - "microstat_eta": { - "type": "number" - }, - "microstat_tau": { - "type": "number" - }, - "num_ctx": { - "type": "integer" - }, - "num_gpu": { - "type": "integer" - }, - "num_gqa": { - "type": "integer" - }, - "num_predict": { - "type": "integer" - }, - "num_thread": { - "type": "integer" - }, - "repeat_last_n": { - "type": "integer" - }, - "seed": { - "type": "integer" - }, - "stop": { - "type": "array", - "items": { - "type": "string" - } - }, - "stream": { - "type": "boolean" - }, - "temperature": { - "type": "number" - }, - "tfs_z": { - "type": "number" - }, - "top_k": { - "type": "integer" - }, - "top_p": { - "type": "number" - } - } - }, - "openai.Config": { - "type": "object", - "required": [ - "baseUrl", - "chatEndpoint", - "model" - ], - "properties": { - "baseUrl": { - "type": "string" - }, - "chatEndpoint": { - "type": "string" - }, - "defaultParams": { - "$ref": "#/definitions/openai.Params" - }, - "model": { + "message": { "type": "string" - } - } - }, - "openai.Params": { - "type": "object", - "properties": { - "frequency_penalty": { - "type": "integer" - }, - "logit_bias": { - "type": "object", - "additionalProperties": { - "type": "number" - } - }, - "max_tokens": { - "type": "integer" - }, - "n": { - "type": "integer" - }, - "presence_penalty": { - "type": "integer" - }, - "response_format": { - "description": "TODO: should this be a part of the chat request API?" }, - "seed": { - "type": "integer" - }, - "stop": { - "type": "array", - "items": { - "type": "string" - } - }, - "temperature": { - "type": "number" - }, - "tool_choice": {}, - "tools": { - "type": "array", - "items": { - "type": "string" - } - }, - "top_p": { - "type": "number" - }, - "user": { + "name": { "type": "string" } } }, - "providers.LangModelConfig": { + "schemas.HealthSchema": { "type": "object", - "required": [ - "enabled", - "id" - ], "properties": { - "anthropic": { - "$ref": "#/definitions/anthropic.Config" - }, - "azureopenai": { - "$ref": "#/definitions/azureopenai.Config" - }, - "bedrock": { - "$ref": "#/definitions/bedrock.Config" - }, - "client": { - "$ref": "#/definitions/clients.ClientConfig" - }, - "cohere": { - "$ref": "#/definitions/cohere.Config" - }, - "enabled": { - "description": "Is the model enabled?", + "healthy": { "type": "boolean" - }, - "error_budget": { - "type": "string" - }, - "id": { - "description": "Model instance ID (unique in scope of the router)", - "type": "string" - }, - "latency": { - "$ref": "#/definitions/latency.Config" - }, - "octoml": { - "$ref": "#/definitions/octoml.Config" - }, - "ollama": { - "$ref": "#/definitions/ollama.Config" - }, - "openai": { - "description": "Add other providers like", - "allOf": [ - { - "$ref": "#/definitions/openai.Config" - } - ] - }, - "weight": { - "type": "integer" - } - } - }, - "retry.ExpRetryConfig": { - "type": "object", - "properties": { - "base_multiplier": { - "type": "integer" - }, - "max_delay": { - "type": "integer" - }, - "max_retries": { - "type": "integer" - }, - "min_delay": { - "type": "integer" } } }, - "routers.LangRouterConfig": { + "schemas.ModelParamsOverride": { "type": "object", - "required": [ - "enabled", - "models", - "retry", - "routers", - "strategy" - ], "properties": { - "enabled": { - "description": "Is router enabled?", - "type": "boolean" - }, - "models": { - "description": "the list of models that could handle requests", - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/definitions/providers.LangModelConfig" - } - }, - "retry": { - "description": "retry when no healthy model is available to router", + "message": { + "description": "TODO: should be just string?", "allOf": [ { - "$ref": "#/definitions/retry.ExpRetryConfig" + "$ref": "#/definitions/schemas.ChatMessage" } ] - }, - "routers": { - "description": "Unique router ID", - "type": "string" - }, - "strategy": { - "description": "strategy on picking the next model to serve the request", - "type": "string" - } - } - }, - "schemas.ChatMessage": { - "type": "object", - "required": [ - "content", - "role" - ], - "properties": { - "content": { - "description": "The content of the message.", - "type": "string" - }, - "name": { - "description": "The name of the author of this message. May contain a-z, A-Z, 0-9, and underscores,\nwith a maximum length of 64 characters.", - "type": "string" - }, - "role": { - "description": "The role of the author of this message. One of system, user, or assistant.", - "type": "string" - } - } - }, - "schemas.ChatRequest": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "$ref": "#/definitions/schemas.ChatMessage" - }, - "messageHistory": { - "type": "array", - "items": { - "$ref": "#/definitions/schemas.ChatMessage" - } - }, - "override": { - "$ref": "#/definitions/schemas.OverrideChatRequest" - } - } - }, - "schemas.ChatResponse": { - "type": "object", - "properties": { - "cached": { - "type": "boolean" - }, - "created": { - "type": "integer" - }, - "id": { - "type": "string" - }, - "model": { - "type": "string" - }, - "modelResponse": { - "$ref": "#/definitions/schemas.ModelResponse" - }, - "model_id": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "router": { - "type": "string" } } }, @@ -888,42 +294,36 @@ "message": { "$ref": "#/definitions/schemas.ChatMessage" }, - "responseId": { + "metadata": { "type": "object", "additionalProperties": { "type": "string" } }, - "tokenCount": { + "token_usage": { "$ref": "#/definitions/schemas.TokenUsage" } } }, - "schemas.OverrideChatRequest": { + "schemas.RouterListSchema": { "type": "object", - "required": [ - "message", - "model_id" - ], "properties": { - "message": { - "$ref": "#/definitions/schemas.ChatMessage" - }, - "model_id": { - "type": "string" + "routers": { + "type": "array", + "items": {} } } }, "schemas.TokenUsage": { "type": "object", "properties": { - "promptTokens": { + "prompt_tokens": { "type": "integer" }, - "responseTokens": { + "response_tokens": { "type": "integer" }, - "totalTokens": { + "total_tokens": { "type": "integer" } } diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 9078f891..82dcc4a6 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1,440 +1,10 @@ basePath: / definitions: - anthropic.Config: - properties: - apiVersion: - type: string - baseUrl: - type: string - chatEndpoint: - type: string - defaultParams: - $ref: '#/definitions/anthropic.Params' - model: - type: string - required: - - apiVersion - - baseUrl - - chatEndpoint - - model - type: object - anthropic.Params: - properties: - max_tokens: - type: integer - metadata: - type: string - stop: - items: - type: string - type: array - system: - type: string - temperature: - type: number - top_k: - type: integer - top_p: - type: number - type: object - azureopenai.Config: - properties: - apiVersion: - description: The API version to use for this operation. This follows the YYYY-MM-DD - format (e.g 2023-05-15) - type: string - baseUrl: - description: The name of your Azure OpenAI Resource (e.g https://glide-test.openai.azure.com/) - type: string - chatEndpoint: - type: string - defaultParams: - $ref: '#/definitions/azureopenai.Params' - model: - description: This is your deployment name. You're required to first deploy - a model before you can make calls (e.g. glide-gpt-35) - type: string - required: - - apiVersion - - baseUrl - - model - type: object - azureopenai.Params: - properties: - frequency_penalty: - type: integer - logit_bias: - additionalProperties: - type: number - type: object - max_tokens: - type: integer - "n": - type: integer - presence_penalty: - type: integer - response_format: - description: 'TODO: should this be a part of the chat request API?' - seed: - type: integer - stop: - items: - type: string - type: array - temperature: - type: number - tool_choice: {} - tools: - items: - type: string - type: array - top_p: - type: number - user: - type: string - type: object - bedrock.Config: - properties: - awsRegion: - type: string - baseUrl: - type: string - chatEndpoint: - type: string - defaultParams: - $ref: '#/definitions/bedrock.Params' - model: - type: string - required: - - awsRegion - - baseUrl - - chatEndpoint - - model - type: object - bedrock.Params: - properties: - max_tokens: - type: integer - stop: - items: - type: string - type: array - temperature: - type: number - top_p: - type: number - type: object - clients.ClientConfig: - properties: - timeout: - type: string - type: object - cohere.Config: - properties: - baseUrl: - type: string - chatEndpoint: - type: string - defaultParams: - $ref: '#/definitions/cohere.Params' - model: - description: https://docs.cohere.com/docs/models#command - type: string - required: - - baseUrl - - chatEndpoint - - model - type: object - cohere.Params: - properties: - connectors: - items: - type: string - type: array - frequency_penalty: - maximum: 1 - minimum: 0 - type: number - k: - maximum: 500 - minimum: 0 - type: integer - max_tokens: - type: integer - p: - maximum: 0.99 - minimum: 0.01 - type: number - preamble: - type: string - presence_penalty: - maximum: 1 - minimum: 0 - type: number - prompt_truncation: - type: string - search_queries_only: - type: boolean - seed: - type: integer - stop_sequences: - items: - type: string - maxItems: 5 - type: array - temperature: - type: number - required: - - temperature - type: object - http.ErrorSchema: - properties: - message: - type: string - type: object - http.HealthSchema: - properties: - healthy: - type: boolean - type: object - http.RouterListSchema: - properties: - routers: - items: - $ref: '#/definitions/routers.LangRouterConfig' - type: array - type: object - latency.Config: - properties: - decay: - description: Weight of new latency measurements - type: number - update_interval: - description: How often gateway should probe models with not the lowest response - latency - type: string - warmup_samples: - description: The number of latency probes required to init moving average - type: integer - type: object - octoml.Config: - properties: - baseUrl: - type: string - chatEndpoint: - type: string - defaultParams: - $ref: '#/definitions/octoml.Params' - model: - type: string - required: - - baseUrl - - chatEndpoint - - model - type: object - octoml.Params: - properties: - frequency_penalty: - type: integer - max_tokens: - type: integer - presence_penalty: - type: integer - stop: - items: - type: string - type: array - temperature: - type: number - top_p: - type: number - type: object - ollama.Config: - properties: - baseUrl: - type: string - chatEndpoint: - type: string - defaultParams: - $ref: '#/definitions/ollama.Params' - model: - type: string - required: - - baseUrl - - chatEndpoint - - model - type: object - ollama.Params: - properties: - microstat: - type: integer - microstat_eta: - type: number - microstat_tau: - type: number - num_ctx: - type: integer - num_gpu: - type: integer - num_gqa: - type: integer - num_predict: - type: integer - num_thread: - type: integer - repeat_last_n: - type: integer - seed: - type: integer - stop: - items: - type: string - type: array - stream: - type: boolean - temperature: - type: number - tfs_z: - type: number - top_k: - type: integer - top_p: - type: number - type: object - openai.Config: - properties: - baseUrl: - type: string - chatEndpoint: - type: string - defaultParams: - $ref: '#/definitions/openai.Params' - model: - type: string - required: - - baseUrl - - chatEndpoint - - model - type: object - openai.Params: - properties: - frequency_penalty: - type: integer - logit_bias: - additionalProperties: - type: number - type: object - max_tokens: - type: integer - "n": - type: integer - presence_penalty: - type: integer - response_format: - description: 'TODO: should this be a part of the chat request API?' - seed: - type: integer - stop: - items: - type: string - type: array - temperature: - type: number - tool_choice: {} - tools: - items: - type: string - type: array - top_p: - type: number - user: - type: string - type: object - providers.LangModelConfig: - properties: - anthropic: - $ref: '#/definitions/anthropic.Config' - azureopenai: - $ref: '#/definitions/azureopenai.Config' - bedrock: - $ref: '#/definitions/bedrock.Config' - client: - $ref: '#/definitions/clients.ClientConfig' - cohere: - $ref: '#/definitions/cohere.Config' - enabled: - description: Is the model enabled? - type: boolean - error_budget: - type: string - id: - description: Model instance ID (unique in scope of the router) - type: string - latency: - $ref: '#/definitions/latency.Config' - octoml: - $ref: '#/definitions/octoml.Config' - ollama: - $ref: '#/definitions/ollama.Config' - openai: - allOf: - - $ref: '#/definitions/openai.Config' - description: Add other providers like - weight: - type: integer - required: - - enabled - - id - type: object - retry.ExpRetryConfig: - properties: - base_multiplier: - type: integer - max_delay: - type: integer - max_retries: - type: integer - min_delay: - type: integer - type: object - routers.LangRouterConfig: - properties: - enabled: - description: Is router enabled? - type: boolean - models: - description: the list of models that could handle requests - items: - $ref: '#/definitions/providers.LangModelConfig' - minItems: 1 - type: array - retry: - allOf: - - $ref: '#/definitions/retry.ExpRetryConfig' - description: retry when no healthy model is available to router - routers: - description: Unique router ID - type: string - strategy: - description: strategy on picking the next model to serve the request - type: string - required: - - enabled - - models - - retry - - routers - - strategy - type: object schemas.ChatMessage: properties: content: description: The content of the message. type: string - name: - description: |- - The name of the author of this message. May contain a-z, A-Z, 0-9, and underscores, - with a maximum length of 64 characters. - type: string role: description: The role of the author of this message. One of system, user, or assistant. @@ -447,12 +17,14 @@ definitions: properties: message: $ref: '#/definitions/schemas.ChatMessage' - messageHistory: + message_history: items: $ref: '#/definitions/schemas.ChatMessage' type: array - override: - $ref: '#/definitions/schemas.OverrideChatRequest' + override_params: + additionalProperties: + $ref: '#/definitions/schemas.ModelParamsOverride' + type: object required: - message type: object @@ -460,49 +32,64 @@ definitions: properties: cached: type: boolean - created: + created_at: type: integer id: type: string - model: - type: string model_id: type: string - modelResponse: + model_name: + type: string + model_response: $ref: '#/definitions/schemas.ModelResponse' - provider: + provider_id: type: string - router: + router_id: type: string type: object + schemas.Error: + properties: + message: + type: string + name: + type: string + type: object + schemas.HealthSchema: + properties: + healthy: + type: boolean + type: object + schemas.ModelParamsOverride: + properties: + message: + allOf: + - $ref: '#/definitions/schemas.ChatMessage' + description: 'TODO: should be just string?' + type: object schemas.ModelResponse: properties: message: $ref: '#/definitions/schemas.ChatMessage' - responseId: + metadata: additionalProperties: type: string type: object - tokenCount: + token_usage: $ref: '#/definitions/schemas.TokenUsage' type: object - schemas.OverrideChatRequest: + schemas.RouterListSchema: properties: - message: - $ref: '#/definitions/schemas.ChatMessage' - model_id: - type: string - required: - - message - - model_id + routers: + items: {} + type: array type: object schemas.TokenUsage: properties: - promptTokens: + prompt_tokens: type: integer - responseTokens: + response_tokens: type: integer - totalTokens: + total_tokens: type: integer type: object externalDocs: @@ -533,7 +120,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/http.HealthSchema' + $ref: '#/definitions/schemas.HealthSchema' summary: Gateway Health tags: - Operations @@ -541,7 +128,7 @@ paths: get: consumes: - application/json - description: Retrieve list of configured language routers and their configurations + description: Retrieve list of configured active language routers and their configurations operationId: glide-language-routers produces: - application/json @@ -549,7 +136,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/http.RouterListSchema' + $ref: '#/definitions/schemas.RouterListSchema' summary: Language Router List tags: - Language @@ -581,11 +168,11 @@ paths: "400": description: Bad Request schema: - $ref: '#/definitions/http.ErrorSchema' + $ref: '#/definitions/schemas.Error' "404": description: Not Found schema: - $ref: '#/definitions/http.ErrorSchema' + $ref: '#/definitions/schemas.Error' summary: Language Chat tags: - Language @@ -628,7 +215,7 @@ paths: "404": description: Not Found schema: - $ref: '#/definitions/http.ErrorSchema' + $ref: '#/definitions/schemas.Error' "426": description: Upgrade Required summary: Language Chat diff --git a/go.mod b/go.mod index 13ccb639..da0c75a3 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ -module glide +module github.com/EinStack/glide -go 1.22.1 +go 1.22.4 require ( github.com/aws/aws-sdk-go-v2 v1.24.1 @@ -9,6 +9,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/bedrockruntime v1.5.6 github.com/go-playground/validator/v10 v10.17.0 github.com/gofiber/contrib/fiberzap/v2 v2.1.2 + github.com/gofiber/contrib/otelfiber v1.0.10 github.com/gofiber/contrib/websocket v1.3.0 github.com/gofiber/fiber/v2 v2.52.2 github.com/gofiber/swagger v1.0.0 @@ -16,8 +17,15 @@ require ( github.com/joho/godotenv v1.5.1 github.com/r3labs/sse/v2 v2.10.0 github.com/spf13/cobra v1.8.0 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 github.com/swaggo/swag v1.16.3 + go.opentelemetry.io/contrib/exporters/autoexport v0.51.0 + go.opentelemetry.io/contrib/instrumentation/host v0.51.0 + go.opentelemetry.io/contrib/instrumentation/runtime v0.51.0 + go.opentelemetry.io/contrib/propagators/b3 v1.26.0 + go.opentelemetry.io/otel v1.26.0 + go.opentelemetry.io/otel/sdk v1.26.0 + go.opentelemetry.io/otel/sdk/metric v1.26.0 go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.26.0 @@ -38,35 +46,69 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 // indirect github.com/aws/smithy-go v1.19.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fasthttp/websocket v1.5.7 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-openapi/jsonpointer v0.20.2 // indirect github.com/go-openapi/jsonreference v0.20.4 // indirect github.com/go-openapi/spec v0.20.13 // indirect github.com/go-openapi/swag v0.22.7 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/klauspost/compress v1.17.6 // indirect github.com/leodido/go-urn v1.2.4 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect + github.com/shirou/gopsutil/v3 v3.24.3 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/swaggo/files/v2 v2.0.0 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.52.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect - golang.org/x/crypto v0.21.0 // indirect - golang.org/x/net v0.21.0 // indirect - golang.org/x/sys v0.18.0 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect + go.opentelemetry.io/contrib v1.17.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0 // indirect + go.opentelemetry.io/otel/metric v1.26.0 // indirect + go.opentelemetry.io/otel/trace v1.26.0 // indirect + go.opentelemetry.io/proto/otlp v1.2.0 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.16.1 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect ) diff --git a/go.sum b/go.sum index 184c944d..f4f03886 100644 --- a/go.sum +++ b/go.sum @@ -32,6 +32,12 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 h1:NzO4Vrau795RkUdSHKEwiR01FaGz github.com/aws/aws-sdk-go-v2/service/sts v1.26.7/go.mod h1:6h2YuIoxaMSCFf5fi1EgZAwdfkGMgDY+DVfa61uLe4U= github.com/aws/smithy-go v1.19.0 h1:KWFKQV80DpP3vJrrA9sVAHQ5gc2z8i4EzrLhLlWXcBM= github.com/aws/smithy-go v1.19.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -40,6 +46,13 @@ github.com/fasthttp/websocket v1.5.7 h1:0a6o2OfeATvtGgoMKleURhLT6JqWPg7fYfWnH4KH github.com/fasthttp/websocket v1.5.7/go.mod h1:bC4fxSono9czeXHQUVKxsC0sNjbm7lPJR04GDFqClfU= github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU= @@ -58,16 +71,22 @@ github.com/go-playground/validator/v10 v10.17.0 h1:SmVVlfAOtlZncTxRuinDPomC2DkXJ github.com/go-playground/validator/v10 v10.17.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/gofiber/contrib/fiberzap/v2 v2.1.2 h1:7Z1BqS1sYK9e9jTwqPcWx9qQt46PI8oeswgAp6YNZC4= github.com/gofiber/contrib/fiberzap/v2 v2.1.2/go.mod h1:ulCCQOdDYABGsOQfbndASmCsCN86hsC96iKoOTNYfy8= +github.com/gofiber/contrib/otelfiber v1.0.10 h1:Bu28Pi4pfYmGfIc/9+sNaBbFwTHGY/zpSIK5jBxuRtM= +github.com/gofiber/contrib/otelfiber v1.0.10/go.mod h1:jN6AvS1HolDHTQHFURsV+7jSX96FpXYeKH6nmkq8AIw= github.com/gofiber/contrib/websocket v1.3.0 h1:XADFAGorer1VJ1bqC4UkCjqS37kwRTV0415+050NrMk= github.com/gofiber/contrib/websocket v1.3.0/go.mod h1:xguaOzn2ZZ759LavtosEP+rcxIgBEE/rdumPINhR+Xo= github.com/gofiber/fiber/v2 v2.52.2 h1:b0rYH6b06Df+4NyrbdptQL8ifuxw/Tf2DgfkZkDaxEo= github.com/gofiber/fiber/v2 v2.52.2/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= github.com/gofiber/swagger v1.0.0 h1:BzUzDS9ZT6fDUa692kxmfOjc1DZiloLiPK/W5z1H1tc= github.com/gofiber/swagger v1.0.0/go.mod h1:QrYNF1Yrc7ggGK6ATsJ6yfH/8Zi5bu9lA7wB8TmCecg= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= @@ -82,6 +101,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -93,6 +114,16 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/r3labs/sse/v2 v2.10.0 h1:hFEkLLFY4LDifoHdiCN/LlGBAdVJYsANaLqNYa1l/v0= github.com/r3labs/sse/v2 v2.10.0/go.mod h1:Igau6Whc+F17QUgML1fYe1VPZzTV6EMCnYktEmkNJ7I= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -103,6 +134,12 @@ github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUz github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk= github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g= +github.com/shirou/gopsutil/v3 v3.24.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhVnuPE= +github.com/shirou/gopsutil/v3 v3.24.3/go.mod h1:JpND7O217xa72ewWz9zN2eIIkPWsDN/3pl0H8Qt0uwg= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -110,22 +147,70 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw= github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM= github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg= github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.52.0 h1:wqBQpxH71XW0e2g+Og4dzQM8pk34aFYlA1Ga8db7gU0= github.com/valyala/fasthttp v1.52.0/go.mod h1:hf5C4QnVMkNXMspnsUlfM3WitlgYflyhHYoKol/szxQ= github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/contrib v1.17.0 h1:lJJdtuNsP++XHD7tXDYEFSpsqIc7DzShuXMR5PwkmzA= +go.opentelemetry.io/contrib v1.17.0/go.mod h1:gIzjwWFoGazJmtCaDgViqOSJPde2mCWzv60o0bWPcZs= +go.opentelemetry.io/contrib/exporters/autoexport v0.51.0 h1:imlL5MBzKu+NWhnJM62bHws6m+6LN8HMT3V9PcSTbaY= +go.opentelemetry.io/contrib/exporters/autoexport v0.51.0/go.mod h1:gn1wFA1uVEKIXrM3DC7SN9ee83oJ0yALY/HbUfqMszo= +go.opentelemetry.io/contrib/instrumentation/host v0.51.0 h1:QljwOKW6+mdod9+lK5SzhPzGtB8XQcLNGddK/wYlMI4= +go.opentelemetry.io/contrib/instrumentation/host v0.51.0/go.mod h1:wYX18WtmQZ45RNcpd0d9uLvjGOd7I2dOoQ4h4LvoVD8= +go.opentelemetry.io/contrib/instrumentation/runtime v0.51.0 h1:1tBjncp/Rr5iuV0WfdKGGynrzIJ8bMm5z7Zl6jMjfIE= +go.opentelemetry.io/contrib/instrumentation/runtime v0.51.0/go.mod h1:6MqTuVXkhmzrIc7SFHYVTo7N6OFvVpDH5eq5xXKpAZQ= +go.opentelemetry.io/contrib/propagators/b3 v1.26.0 h1:wgFbVA+bK2k+fGVfDOCOG4cfDAoppyr5sI2dVlh8MWM= +go.opentelemetry.io/contrib/propagators/b3 v1.26.0/go.mod h1:DDktFXxA+fyItAAM0Sbl5OBH7KOsCTjvbBdPKtoIf/k= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 h1:+hm+I+KigBy3M24/h1p/NHkUx/evbLH0PNcjpMyCHc4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0/go.mod h1:NjC8142mLvvNT6biDpaMjyz78kyEHIwAJlSX0N9P5KI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 h1:HGZWGmCVRCVyAs2GQaiHQPbDHo+ObFWeUEOd+zDnp64= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0/go.mod h1:SaH+v38LSCHddyk7RGlU9uZyQoRrKao6IBnJw6Kbn+c= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 h1:1u/AyyOqAWzy+SkPxDpahCNZParHV8Vid1RnI2clyDE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0/go.mod h1:z46paqbJ9l7c9fIPCXTqTGwhQZ5XoTIsfeFYWboizjs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 h1:Waw9Wfpo/IXzOI8bCB7DIk+0JZcqqsyn1JFnAc+iam8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0/go.mod h1:wnJIG4fOqyynOnnQF/eQb4/16VlX2EJAHhHgqIqWfAo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 h1:1wp/gyxsuYtuE/JFxsQRtcCDtMrO2qMvlfXALU5wkzI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0/go.mod h1:gbTHmghkGgqxMomVQQMur1Nba4M0MQ8AYThXDUjsJ38= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 h1:5fnmgteaar1VcAA69huatudPduNFz7guRtCmfZCooZI= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0/go.mod h1:lsPccfZiz1cb1AhBPmicWM2E4F1VynFXEvD8SEBS4TM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0 h1:0W5o9SzoR15ocYHEQfvfipzcNog1lBxOLfnex91Hk6s= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.26.0/go.mod h1:zVZ8nz+VSggWmnh6tTsJqXQ7rU4xLwRtna1M4x5jq58= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/oteltest v1.0.0-RC3 h1:MjaeegZTaX0Bv9uB9CrdVjOFM/8slRjReoWoV9xDCpY= +go.opentelemetry.io/otel/oteltest v1.0.0-RC3/go.mod h1:xpzajI9JBRr7gX63nO6kAmImmYIAtuQblZ36Z+LfCjE= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= +go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -133,23 +218,39 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8 go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20191116160921-f9c825593386/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y= gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UDAkHu8BrjI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/images/Makefile b/images/Makefile index 145f8b59..d87148ac 100644 --- a/images/Makefile +++ b/images/Makefile @@ -2,7 +2,7 @@ VENDOR ?= einstack PROJECT ?= Glide SOURCE ?= https://github.com/EinStack/glide LICENSE ?= Apache-2.0 -DESCRIPTION ?= "A lightweight, cloud-native LLM gateway" +DESCRIPTION ?= "A lightweight, cloud-native fast LLM gateway" REPOSITORY ?= einstack/glide VERSION ?= dev @@ -10,7 +10,6 @@ RC_PART ?= rc COMMIT ?= $(shell git describe --dirty --always --abbrev=15) BUILD_DATE ?= $(shell date -u +"%Y-%m-%dT%H:%M:%SZ") - # OCI Labels: https://specs.opencontainers.org/image-spec/annotations # Test images via: docker run --rm --platform linux/amd64 -i einstack/glide:dev-alpine --config config.dev.yaml diff --git a/images/alpine.Dockerfile b/images/alpine.Dockerfile index 26b20357..31d48df5 100644 --- a/images/alpine.Dockerfile +++ b/images/alpine.Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM golang:1.22-alpine as build +FROM golang:1.22.4-alpine as build ARG VERSION ARG COMMIT @@ -11,7 +11,7 @@ WORKDIR /build COPY . /build/ RUN go mod download -RUN go build -ldflags "-s -w -X glide/pkg.version=$VERSION -X glide/pkg.commitSha=$COMMIT -X glide/pkg.buildDate=$BUILD_DATE" -o /build/dist/glide +RUN go build -ldflags "-s -w -X glide/pkg/version.Version=$VERSION -X glide/pkg/version.commitSha=$COMMIT -X glide/pkg/version.buildDate=$BUILD_DATE" -o /build/dist/glide FROM alpine:3.19 as release diff --git a/images/distroless.Dockerfile b/images/distroless.Dockerfile index 23167563..85f0683e 100644 --- a/images/distroless.Dockerfile +++ b/images/distroless.Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM golang:1.22-alpine as build +FROM golang:1.22.4-alpine as build ARG VERSION ARG COMMIT @@ -11,7 +11,7 @@ WORKDIR /build COPY . /build/ RUN go mod download -RUN go build -ldflags "-s -w -X glide/pkg.version=$VERSION -X glide/pkg.commitSha=$COMMIT -X glide/pkg.buildDate=$BUILD_DATE" -o /build/dist/glide +RUN go build -ldflags "-s -w -X glide/pkg/version.Version=$VERSION -X glide/pkg/version.commitSha=$COMMIT -X glide/pkg/version.buildDate=$BUILD_DATE" -o /build/dist/glide FROM gcr.io/distroless/static-debian12:nonroot as release diff --git a/images/redhat.Dockerfile b/images/redhat.Dockerfile index c3a16248..4872adcb 100644 --- a/images/redhat.Dockerfile +++ b/images/redhat.Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM golang:1.22-alpine as build +FROM golang:1.22.4-alpine as build ARG VERSION ARG COMMIT @@ -11,7 +11,7 @@ WORKDIR /build COPY . /build/ RUN go mod download -RUN go build -ldflags "-s -w -X glide/pkg.version=$VERSION -X glide/pkg.commitSha=$COMMIT -X glide/pkg.buildDate=$BUILD_DATE" -o /build/dist/glide +RUN go build -ldflags "-s -w -X glide/pkg/version.version=$VERSION -X glide/pkg/version.commitSha=$COMMIT -X glide/pkg/version.buildDate=$BUILD_DATE" -o /build/dist/glide FROM redhat/ubi8-micro:8.9 as release diff --git a/images/ubuntu.Dockerfile b/images/ubuntu.Dockerfile index fe238b79..3daf566a 100644 --- a/images/ubuntu.Dockerfile +++ b/images/ubuntu.Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM golang:1.22-alpine as build +FROM golang:1.22.4-alpine as build ARG VERSION ARG COMMIT @@ -11,7 +11,7 @@ WORKDIR /build COPY . /build/ RUN go mod download -RUN go build -ldflags "-s -w -X glide/pkg.version=$VERSION -X glide/pkg.commitSha=$COMMIT -X glide/pkg.buildDate=$BUILD_DATE" -o /build/dist/glide +RUN go build -ldflags "-s -w -X glide/pkg/version.version=$VERSION -X glide/pkg/version.commitSha=$COMMIT -X glide/pkg/version.buildDate=$BUILD_DATE" -o /build/dist/glide FROM ubuntu:22.04 as release diff --git a/main.go b/main.go index 0173f5ff..a6d84381 100644 --- a/main.go +++ b/main.go @@ -3,7 +3,7 @@ package main import ( "log" - "glide/pkg/cmd" + "github.com/EinStack/glide/pkg/cmd" ) // @title Glide diff --git a/pkg/api/config.go b/pkg/api/config.go index c1edbb20..ecd15dd1 100644 --- a/pkg/api/config.go +++ b/pkg/api/config.go @@ -1,6 +1,6 @@ package api -import "glide/pkg/api/http" +import "github.com/EinStack/glide/pkg/api/http" // Config defines configuration for all API types we support (e.g. HTTP, gRPC) type Config struct { diff --git a/pkg/api/http/config.go b/pkg/api/http/config.go index e9098266..0f5f838e 100644 --- a/pkg/api/http/config.go +++ b/pkg/api/http/config.go @@ -4,8 +4,8 @@ import ( "fmt" "time" + "github.com/EinStack/glide/pkg/version" "github.com/gofiber/fiber/v2" - "glide/pkg/version" ) type ServerConfig struct { diff --git a/pkg/api/http/handlers.go b/pkg/api/http/handlers.go index f7cbd20a..98e9f3a3 100644 --- a/pkg/api/http/handlers.go +++ b/pkg/api/http/handlers.go @@ -2,16 +2,14 @@ package http import ( "context" - "errors" "sync" - "glide/pkg/telemetry" - "go.uber.org/zap" - + "github.com/EinStack/glide/pkg/api/schemas" + "github.com/EinStack/glide/pkg/routers" + "github.com/EinStack/glide/pkg/telemetry" "github.com/gofiber/contrib/websocket" "github.com/gofiber/fiber/v2" - "glide/pkg/api/schemas" - "glide/pkg/routers" + "go.uber.org/zap" ) type Handler = func(c *fiber.Ctx) error @@ -30,45 +28,43 @@ type Handler = func(c *fiber.Ctx) error // @Accept json // @Produce json // @Success 200 {object} schemas.ChatResponse -// @Failure 400 {object} http.ErrorSchema -// @Failure 404 {object} http.ErrorSchema +// @Failure 400 {object} schemas.Error +// @Failure 404 {object} schemas.Error // @Router /v1/language/{router}/chat [POST] func LangChatHandler(routerManager *routers.RouterManager) Handler { return func(c *fiber.Ctx) error { if !c.Is("json") { - return c.Status(fiber.StatusBadRequest).JSON(ErrorSchema{ - Message: "Glide accepts only JSON payloads", - }) + return c.Status(fiber.StatusBadRequest).JSON(schemas.ErrUnsupportedMediaType) } // Unmarshal request body - var req *schemas.ChatRequest + req := schemas.GetChatRequest() + defer schemas.ReleaseChatRequest(req) err := c.BodyParser(&req) if err != nil { - return c.Status(fiber.StatusBadRequest).JSON(ErrorSchema{ - Message: err.Error(), - }) + return c.Status(fiber.StatusBadRequest).JSON(schemas.NewPayloadParseErr(err)) } // Get router ID from path routerID := c.Params("router") + router, err := routerManager.GetLangRouter(routerID) + if err != nil { + httpErr := schemas.FromErr(err) - if errors.Is(err, routers.ErrRouterNotFound) { - // Return not found error - return c.Status(fiber.StatusNotFound).JSON(ErrorSchema{ - Message: err.Error(), - }) + return c.Status(httpErr.Status).JSON(httpErr) } // Chat with router - resp, err := router.Chat(c.Context(), req) + resp := schemas.GetChatResponse() + defer schemas.ReleaseChatResponse(resp) + + resp, err = router.Chat(c.Context(), req) if err != nil { - // Return internal server error - return c.Status(fiber.StatusInternalServerError).JSON(ErrorSchema{ - Message: err.Error(), - }) + httpErr := schemas.FromErr(err) + + return c.Status(httpErr.Status).JSON(httpErr) } // Return chat response @@ -83,9 +79,9 @@ func LangStreamRouterValidator(routerManager *routers.RouterManager) Handler { _, err := routerManager.GetLangRouter(routerID) if err != nil { - return c.Status(fiber.StatusNotFound).JSON(ErrorSchema{ - Message: err.Error(), - }) + httpErr := schemas.FromErr(err) + + return c.Status(httpErr.Status).JSON(httpErr) } return c.Next() @@ -109,7 +105,7 @@ func LangStreamRouterValidator(routerManager *routers.RouterManager) Handler { // @Accept json // @Success 101 // @Failure 426 -// @Failure 404 {object} http.ErrorSchema +// @Failure 404 {object} schemas.Error // @Router /v1/language/{router}/chatStream [GET] func LangStreamChatHandler(tel *telemetry.Telemetry, routerManager *routers.RouterManager) Handler { // TODO: expose websocket connection configs https://github.com/gofiber/contrib/tree/main/websocket @@ -145,6 +141,7 @@ func LangStreamChatHandler(tel *telemetry.Telemetry, routerManager *routers.Rout var chatRequest schemas.ChatStreamRequest if err = c.ReadJSON(&chatRequest); err != nil { + // TODO: handle bad request schemas gracefully and return back validation errors if websocket.IsUnexpectedCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway) { tel.L().Warn("Streaming Chat connection is closed", zap.Error(err), zap.String("routerID", routerID)) } @@ -172,22 +169,22 @@ func LangStreamChatHandler(tel *telemetry.Telemetry, routerManager *routers.Rout // // @id glide-language-routers // @Summary Language Router List -// @Description Retrieve list of configured language routers and their configurations +// @Description Retrieve list of configured active language routers and their configurations // @tags Language // @Accept json // @Produce json -// @Success 200 {object} http.RouterListSchema +// @Success 200 {object} schemas.RouterListSchema // @Router /v1/language/ [GET] func LangRoutersHandler(routerManager *routers.RouterManager) Handler { return func(c *fiber.Ctx) error { configuredRouters := routerManager.GetLangRouters() - cfgs := make([]*routers.LangRouterConfig, 0, len(configuredRouters)) + cfgs := make([]interface{}, 0, len(configuredRouters)) // opaque by design for _, router := range configuredRouters { cfgs = append(cfgs, router.Config) } - return c.Status(fiber.StatusOK).JSON(RouterListSchema{Routers: cfgs}) + return c.Status(fiber.StatusOK).JSON(schemas.RouterListSchema{Routers: cfgs}) } } @@ -199,14 +196,12 @@ func LangRoutersHandler(routerManager *routers.RouterManager) Handler { // @tags Operations // @Accept json // @Produce json -// @Success 200 {object} http.HealthSchema +// @Success 200 {object} schemas.HealthSchema // @Router /v1/health/ [get] func HealthHandler(c *fiber.Ctx) error { - return c.Status(fiber.StatusOK).JSON(HealthSchema{Healthy: true}) + return c.Status(fiber.StatusOK).JSON(schemas.HealthSchema{Healthy: true}) } func NotFoundHandler(c *fiber.Ctx) error { - return c.Status(fiber.StatusNotFound).JSON(ErrorSchema{ - Message: "The route is not found", - }) + return c.Status(fiber.StatusNotFound).JSON(schemas.ErrRouteNotFound) } diff --git a/pkg/api/http/schemas.go b/pkg/api/http/schemas.go deleted file mode 100644 index e69bd94f..00000000 --- a/pkg/api/http/schemas.go +++ /dev/null @@ -1,15 +0,0 @@ -package http - -import "glide/pkg/routers" - -type ErrorSchema struct { - Message string `json:"message"` -} - -type HealthSchema struct { - Healthy bool `json:"healthy"` -} - -type RouterListSchema struct { - Routers []*routers.LangRouterConfig `json:"routers"` -} diff --git a/pkg/api/http/server.go b/pkg/api/http/server.go index 094b6c4f..9b70a05f 100644 --- a/pkg/api/http/server.go +++ b/pkg/api/http/server.go @@ -6,18 +6,20 @@ import ( "fmt" "time" + "github.com/gofiber/contrib/otelfiber" + "github.com/gofiber/swagger" - "glide/docs" + "github.com/EinStack/glide/docs" + _ "github.com/EinStack/glide/docs" // importing docs package to include them into the binary "github.com/gofiber/contrib/fiberzap/v2" "github.com/gofiber/fiber/v2" - _ "glide/docs" // importing docs package to include them into the binary - "glide/pkg/routers" + "github.com/EinStack/glide/pkg/routers" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" ) type Server struct { @@ -44,6 +46,8 @@ func (srv *Server) Run() error { return c.Status(fiber.StatusOK).Type("json").Send(docs.SwaggerJSON) }) + srv.server.Use(otelfiber.Middleware()) + srv.server.Use(fiberzap.New(fiberzap.Config{ Logger: srv.telemetry.Logger, })) diff --git a/pkg/api/schemas/chat.go b/pkg/api/schemas/chat.go index 4be88692..bb846043 100644 --- a/pkg/api/schemas/chat.go +++ b/pkg/api/schemas/chat.go @@ -2,14 +2,61 @@ package schemas // ChatRequest defines Glide's Chat Request Schema unified across all language models type ChatRequest struct { - Message ChatMessage `json:"message" validate:"required"` - MessageHistory []ChatMessage `json:"messageHistory"` - Override *OverrideChatRequest `json:"override,omitempty"` + Message ChatMessage `json:"message" validate:"required"` + MessageHistory []ChatMessage `json:"message_history,omitempty"` + OverrideParams *map[string]ModelParamsOverride `json:"override_params,omitempty"` } -type OverrideChatRequest struct { - Model string `json:"model_id" validate:"required"` - Message ChatMessage `json:"message" validate:"required"` +func (r *ChatRequest) ModelParams(modelNameOrID string) *ModelParamsOverride { + if r.OverrideParams == nil { + return nil + } + + if override, found := (*r.OverrideParams)[modelNameOrID]; found { + return &override + } + + return nil +} + +// ModelParamsOverride allows to redefine chat message and model params based on the model ID +// +// Glide provides an abstraction around concreate models and this is a way to be able to provide model-specific params if needed. +// The override is going to be applied if Glide picks the referenced there (it may pick another model to serve a given request) +type ModelParamsOverride struct { + // TODO: should be just string? + Message ChatMessage `json:"message,omitempty"` + // TODO(185): Add an ability to override model params +} + +// ChatParams represents a chat request params that overrides the default model params from configs +type ChatParams struct { + Messages []ChatMessage + // TODO(185): set other params +} + +// Params returns a specific chat request params account for model-specific overrides. +func (r *ChatRequest) Params(modelID string, modelName string) *ChatParams { + params := &ChatParams{ + Messages: make([]ChatMessage, 0, len(r.MessageHistory)+1), + } + + reqMessage := r.Message + + if override := r.ModelParams(modelName); override != nil { + // TODO(185): set other params + reqMessage = override.Message + } + + if override := r.ModelParams(modelID); override != nil { + // TODO(185): set other params + reqMessage = override.Message + } + + params.Messages = append(params.Messages, r.MessageHistory...) + params.Messages = append(params.Messages, reqMessage) + + return params } func NewChatFromStr(message string) *ChatRequest { @@ -17,35 +64,33 @@ func NewChatFromStr(message string) *ChatRequest { Message: ChatMessage{ "user", message, - "glide", }, } } // ChatResponse defines Glide's Chat Response Schema unified across all language models type ChatResponse struct { - ID string `json:"id,omitempty"` - Created int `json:"created,omitempty"` - Provider string `json:"provider,omitempty"` - RouterID string `json:"router,omitempty"` - ModelID string `json:"model_id,omitempty"` - ModelName string `json:"model,omitempty"` - Cached bool `json:"cached,omitempty"` - ModelResponse ModelResponse `json:"modelResponse,omitempty"` + ID string `json:"id"` + Created int `json:"created_at"` + Provider string `json:"provider_id"` + RouterID string `json:"router_id"` + ModelID string `json:"model_id"` + ModelName string `json:"model_name"` + Cached bool `json:"cached"` + ModelResponse ModelResponse `json:"model_response"` } // ModelResponse is the unified response from the provider. - type ModelResponse struct { - SystemID map[string]string `json:"responseId,omitempty"` + Metadata map[string]string `json:"metadata"` Message ChatMessage `json:"message"` - TokenUsage TokenUsage `json:"tokenCount"` + TokenUsage TokenUsage `json:"token_usage"` } type TokenUsage struct { - PromptTokens int `json:"promptTokens"` - ResponseTokens int `json:"responseTokens"` - TotalTokens int `json:"totalTokens"` + PromptTokens int `json:"prompt_tokens"` + ResponseTokens int `json:"response_tokens"` + TotalTokens int `json:"total_tokens"` } // ChatMessage is a message in a chat request. @@ -54,7 +99,4 @@ type ChatMessage struct { Role string `json:"role" validate:"required"` // The content of the message. Content string `json:"content" validate:"required"` - // The name of the author of this message. May contain a-z, A-Z, 0-9, and underscores, - // with a maximum length of 64 characters. - Name string `json:"name,omitempty"` } diff --git a/pkg/api/schemas/chat_stream.go b/pkg/api/schemas/chat_stream.go index 983d2242..f7cf8b27 100644 --- a/pkg/api/schemas/chat_stream.go +++ b/pkg/api/schemas/chat_stream.go @@ -6,41 +6,33 @@ type ( Metadata = map[string]any EventType = string FinishReason = string - ErrorCode = string ) var ( - Complete FinishReason = "complete" - MaxTokens FinishReason = "max_tokens" - ContentFiltered FinishReason = "content_filtered" - ErrorReason FinishReason = "error" - OtherReason FinishReason = "other" -) - -var ( - NoModelConfigured ErrorCode = "no_model_configured" - ModelUnavailable ErrorCode = "model_unavailable" - AllModelsUnavailable ErrorCode = "all_models_unavailable" - UnknownError ErrorCode = "unknown_error" + ReasonComplete FinishReason = "complete" + ReasonMaxTokens FinishReason = "max_tokens" + ReasonContentFiltered FinishReason = "content_filtered" + ReasonError FinishReason = "error" + ReasonOther FinishReason = "other" ) type StreamRequestID = string // ChatStreamRequest defines a message that requests a new streaming chat type ChatStreamRequest struct { - ID StreamRequestID `json:"id" validate:"required"` - Message ChatMessage `json:"message" validate:"required"` - MessageHistory []ChatMessage `json:"messageHistory" validate:"required"` - Override *OverrideChatRequest `json:"overrideMessage,omitempty"` - Metadata *Metadata `json:"metadata,omitempty"` + ID StreamRequestID `json:"id" validate:"required"` + *ChatRequest + OverrideParams *map[string]ModelParamsOverride `json:"override_params,omitempty"` + Metadata *Metadata `json:"metadata,omitempty"` } func NewChatStreamFromStr(message string) *ChatStreamRequest { return &ChatStreamRequest{ - Message: ChatMessage{ - "user", - message, - "glide", + ChatRequest: &ChatRequest{ + Message: ChatMessage{ + "user", + message, + }, }, } } @@ -52,8 +44,8 @@ type ModelChunkResponse struct { type ChatStreamMessage struct { ID StreamRequestID `json:"id"` - CreatedAt int `json:"createdAt"` - RouterID string `json:"routerId"` + CreatedAt int `json:"created_at"` + RouterID string `json:"router_id"` Metadata *Metadata `json:"metadata,omitempty"` Chunk *ChatStreamChunk `json:"chunk,omitempty"` Error *ChatStreamError `json:"error,omitempty"` @@ -61,18 +53,18 @@ type ChatStreamMessage struct { // ChatStreamChunk defines a message for a chunk of streaming chat response type ChatStreamChunk struct { - ModelID string `json:"modelId"` - Provider string `json:"providerName"` - ModelName string `json:"modelName"` + ModelID string `json:"model_id"` + Provider string `json:"provider_id"` + ModelName string `json:"model_name"` Cached bool `json:"cached"` - ModelResponse ModelChunkResponse `json:"modelResponse"` - FinishReason *FinishReason `json:"finishReason,omitempty"` + ModelResponse ModelChunkResponse `json:"model_response"` + FinishReason *FinishReason `json:"finish_reason,omitempty"` } type ChatStreamError struct { - ErrCode ErrorCode `json:"errCode"` + Name ErrorName `json:"name"` Message string `json:"message"` - FinishReason *FinishReason `json:"finishReason,omitempty"` + FinishReason *FinishReason `json:"finish_reason,omitempty"` } func NewChatStreamChunk( @@ -93,7 +85,7 @@ func NewChatStreamChunk( func NewChatStreamError( reqID StreamRequestID, routerID string, - errCode ErrorCode, + errName ErrorName, errMsg string, reqMetadata *Metadata, finishReason *FinishReason, @@ -104,7 +96,7 @@ func NewChatStreamError( CreatedAt: int(time.Now().UTC().Unix()), Metadata: reqMetadata, Error: &ChatStreamError{ - ErrCode: errCode, + Name: errName, Message: errMsg, FinishReason: finishReason, }, diff --git a/pkg/api/schemas/chat_test.go b/pkg/api/schemas/chat_test.go new file mode 100644 index 00000000..9b5ce407 --- /dev/null +++ b/pkg/api/schemas/chat_test.go @@ -0,0 +1,170 @@ +package schemas + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func ToSlice(messageHistory []ChatMessage) []string { + history := make([]string, 0, len(messageHistory)) + + for _, message := range messageHistory { + history = append(history, message.Content) + } + + return history +} + +// TestChatRequest_DefaultParams tests param creation for a request +// that doesn't have any override for a given model ID/name +func TestChatRequest_DefaultParams(t *testing.T) { + backstory := "You are talking to a guy who won an ACMP contest in 2015" + defaultMessage := "When did I win an ACMP contest?" + + modelID := "my-openai-model" + myModelMessage := "When did he win the contest?Be concise" + + secondModelID := "my-other-model" + secondModelName := "command-r" + + chatReq := ChatRequest{ + Message: ChatMessage{ + Role: "user", + Content: defaultMessage, + }, + MessageHistory: []ChatMessage{ + { + Role: "system", + Content: backstory, + }, + }, + OverrideParams: &map[string]ModelParamsOverride{ + modelID: { + Message: ChatMessage{ + Role: "user", + Content: myModelMessage, + }, + }, + }, + } + + params := chatReq.Params(secondModelID, secondModelName) + + require.Equal(t, []string{backstory, defaultMessage}, ToSlice(params.Messages)) +} + +// TestChatRequest_ModelIDOverride tests param creation for a request +// that has a param override for a modelID +func TestChatRequest_ModelIDOverride(t *testing.T) { + backstory := "You are talking to a guy who won an ACMP contest in 2015" + defaultMessage := "When did I win an ACMP contest?" + + modelID := "my-openai-model" + modelName := "gpt-4" + myModelMessage := "When did he win the contest?Be concise" + + chatReq := ChatRequest{ + Message: ChatMessage{ + Role: "user", + Content: defaultMessage, + }, + MessageHistory: []ChatMessage{ + { + Role: "system", + Content: backstory, + }, + }, + OverrideParams: &map[string]ModelParamsOverride{ + modelID: { + Message: ChatMessage{ + Role: "user", + Content: myModelMessage, + }, + }, + }, + } + + params := chatReq.Params(modelID, modelName) + + require.Equal(t, []string{backstory, myModelMessage}, ToSlice(params.Messages)) +} + +// TestChatRequest_ModelNameOverride tests param creation for a request +// that has a param override for a modelName +func TestChatRequest_ModelNameOverride(t *testing.T) { + backstory := "You are talking to a guy who won an ACMP contest in 2015" + defaultMessage := "When did I win an ACMP contest?" + + modelID := "my-openai-model" + modelName := "gpt-4" + myModelMessage := "When did he win the contest?Be concise" + + chatReq := ChatRequest{ + Message: ChatMessage{ + Role: "user", + Content: defaultMessage, + }, + MessageHistory: []ChatMessage{ + { + Role: "system", + Content: backstory, + }, + }, + OverrideParams: &map[string]ModelParamsOverride{ + modelName: { + Message: ChatMessage{ + Role: "user", + Content: myModelMessage, + }, + }, + }, + } + + params := chatReq.Params(modelID, modelName) + + require.Equal(t, []string{backstory, myModelMessage}, ToSlice(params.Messages)) +} + +// TestChatRequest_ModelNameOverride tests param creation for a request +// that has a param override for both modelName & modelID +func TestChatRequest_ModelNameIDOverride(t *testing.T) { + backstory := "You are talking to a guy who won an ACMP contest in 2015" + defaultMessage := "When did I win an ACMP contest?" + + modelID := "my-openai-model" + modelName := "gpt-4" + myModelIDMessage := "When did he win the contest?Be concise" + myModelNameMessage := "When did he win the contest? Answer like Illya would" + + chatReq := ChatRequest{ + Message: ChatMessage{ + Role: "user", + Content: defaultMessage, + }, + MessageHistory: []ChatMessage{ + { + Role: "system", + Content: backstory, + }, + }, + OverrideParams: &map[string]ModelParamsOverride{ + modelName: { + Message: ChatMessage{ + Role: "user", + Content: myModelNameMessage, + }, + }, + modelID: { + Message: ChatMessage{ + Role: "user", + Content: myModelIDMessage, + }, + }, + }, + } + + params := chatReq.Params(modelID, modelName) + + require.Equal(t, []string{backstory, myModelIDMessage}, ToSlice(params.Messages)) +} diff --git a/pkg/api/schemas/errors.go b/pkg/api/schemas/errors.go new file mode 100644 index 00000000..2765f93e --- /dev/null +++ b/pkg/api/schemas/errors.go @@ -0,0 +1,79 @@ +package schemas + +import ( + "fmt" + + "github.com/gofiber/fiber/v2" +) + +type ErrorName = string + +var ( + UnsupportedMediaType ErrorName = "unsupported_media_type" + RouteNotFound ErrorName = "route_not_found" + PayloadParseError ErrorName = "payload_parse_error" + RouterNotFound ErrorName = "router_not_found" + NoModelConfigured ErrorName = "no_model_configured" + ModelUnavailable ErrorName = "model_unavailable" + AllModelsUnavailable ErrorName = "all_models_unavailable" + UnknownError ErrorName = "unknown_error" +) + +// Error / Error contains more context than the built-in error type, +// so we know information like error code and message that are useful to propagate to clients +type Error struct { + Status int `json:"-"` + Name string `json:"name"` + Message string `json:"message"` +} + +var _ error = (*Error)(nil) + +// Error returns the error message. +func (e *Error) Error() string { + return fmt.Sprintf("Error (%s): %s", e.Name, e.Message) +} + +func NewError(status int, name string, message string) Error { + return Error{Status: status, Name: name, Message: message} +} + +var ErrUnsupportedMediaType = NewError( + fiber.StatusBadRequest, + UnsupportedMediaType, + "application/json is the only supported media type", +) + +var ErrRouteNotFound = NewError( + fiber.StatusNotFound, + RouteNotFound, + "requested route is not found or method is not allowed", +) + +var ErrRouterNotFound = NewError(fiber.StatusNotFound, RouterNotFound, "router is not found") + +var ErrNoModelAvailable = NewError( + 503, + AllModelsUnavailable, + "all providers are unavailable", +) + +func NewPayloadParseErr(err error) Error { + return NewError( + fiber.StatusBadRequest, + PayloadParseError, + err.Error(), + ) +} + +func FromErr(err error) Error { + if apiErr, ok := err.(*Error); ok { + return *apiErr + } + + return NewError( + fiber.StatusInternalServerError, + UnknownError, + err.Error(), + ) +} diff --git a/pkg/api/schemas/health_checks.go b/pkg/api/schemas/health_checks.go new file mode 100644 index 00000000..6078e769 --- /dev/null +++ b/pkg/api/schemas/health_checks.go @@ -0,0 +1,5 @@ +package schemas + +type HealthSchema struct { + Healthy bool `json:"healthy"` +} diff --git a/pkg/api/schemas/pool.go b/pkg/api/schemas/pool.go new file mode 100755 index 00000000..dcd9ccf8 --- /dev/null +++ b/pkg/api/schemas/pool.go @@ -0,0 +1,39 @@ +package schemas + +import ( + "sync" +) + +var chatRequestPool = sync.Pool{ + New: func() interface{} { + return &ChatRequest{} + }, +} + +var chatResponsePool = sync.Pool{ + New: func() interface{} { + return &ChatResponse{} + }, +} + +// GetChatRequest get objects from the pool +func GetChatRequest() *ChatRequest { + return chatRequestPool.Get().(*ChatRequest) +} + +// ReleaseChatRequest release objects from the pool +func ReleaseChatRequest(req *ChatRequest) { + *req = ChatRequest{} + chatRequestPool.Put(req) +} + +// GetChatResponse get objects from the pool +func GetChatResponse() *ChatResponse { + return chatResponsePool.Get().(*ChatResponse) +} + +// ReleaseChatResponse release objects from the pool +func ReleaseChatResponse(res *ChatResponse) { + *res = ChatResponse{} + chatResponsePool.Put(res) +} diff --git a/pkg/api/schemas/routers.go b/pkg/api/schemas/routers.go new file mode 100644 index 00000000..9111a319 --- /dev/null +++ b/pkg/api/schemas/routers.go @@ -0,0 +1,9 @@ +package schemas + +// RouterListSchema returns list of active configured routers. +// +// Routers config is exposed as an opaque value to indicate that user services must not use it to base any logic on it. +// The endpoint is used for debugging/informational reasons +type RouterListSchema struct { + Routers []interface{} `json:"routers"` +} diff --git a/pkg/api/servers.go b/pkg/api/servers.go index 7a1d3c0d..3588e257 100644 --- a/pkg/api/servers.go +++ b/pkg/api/servers.go @@ -6,11 +6,11 @@ import ( "go.uber.org/zap" - "glide/pkg/routers" + "github.com/EinStack/glide/pkg/routers" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" - "glide/pkg/api/http" + "github.com/EinStack/glide/pkg/api/http" ) type ServerManager struct { diff --git a/pkg/cmd/cli.go b/pkg/cmd/cli.go index 60068884..af71d0d2 100644 --- a/pkg/cmd/cli.go +++ b/pkg/cmd/cli.go @@ -3,11 +3,13 @@ package cmd import ( "log" - "glide/pkg/version" + "github.com/EinStack/glide/pkg/version" + + "github.com/EinStack/glide/pkg/config" + + "github.com/EinStack/glide/pkg" "github.com/spf13/cobra" - "glide/pkg" - "glide/pkg/config" ) var ( @@ -37,7 +39,7 @@ to make your LLM applications production ready πŸŽ‰ func NewCLI() *cobra.Command { // TODO: Chances are we could use the build in flags module in this is all we need from CLI cli := &cobra.Command{ - Use: "glide", + Use: "github.com/EinStack/glide", Short: "🐦Glide is an open-source, lightweight, high-performance model gateway", Long: Description, Version: version.FullVersion, diff --git a/pkg/config/config.go b/pkg/config/config.go index e792688e..dd520a9a 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -1,9 +1,11 @@ package config import ( - "glide/pkg/api" - "glide/pkg/routers" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/routers" + + "github.com/EinStack/glide/pkg/api" ) // Config is a general top-level Glide configuration diff --git a/pkg/gateway.go b/pkg/gateway.go index c372482a..950ec26d 100644 --- a/pkg/gateway.go +++ b/pkg/gateway.go @@ -7,16 +7,19 @@ import ( "os/signal" "syscall" - "glide/pkg/version" + "github.com/EinStack/glide/pkg/routers" + "github.com/EinStack/glide/pkg/version" + "go.opentelemetry.io/contrib/instrumentation/host" + "go.opentelemetry.io/contrib/instrumentation/runtime" - "glide/pkg/routers" + "github.com/EinStack/glide/pkg/config" - "glide/pkg/config" + "github.com/EinStack/glide/pkg/telemetry" - "glide/pkg/telemetry" "go.uber.org/zap" - "glide/pkg/api" + "github.com/EinStack/glide/pkg/api" + "go.uber.org/multierr" ) @@ -67,6 +70,17 @@ func NewGateway(configProvider *config.Provider) (*Gateway, error) { // Run starts and runs the gateway according to given configuration func (gw *Gateway) Run(ctx context.Context) error { + // Instrument the gateway process + err := host.Start() + if err != nil { + return err + } + + err = runtime.Start() + if err != nil { + return err + } + gw.configProvider.Start() gw.serverManager.Start() //nolint:contextcheck diff --git a/pkg/providers/anthropic/chat.go b/pkg/providers/anthropic/chat.go index dc8f857d..80b45f2b 100644 --- a/pkg/providers/anthropic/chat.go +++ b/pkg/providers/anthropic/chat.go @@ -9,33 +9,34 @@ import ( "net/http" "time" - "glide/pkg/api/schemas" + "github.com/EinStack/glide/pkg/providers/clients" + + "github.com/EinStack/glide/pkg/api/schemas" "go.uber.org/zap" ) -type ChatMessage struct { - Role string `json:"role"` - Content string `json:"content"` -} - // ChatRequest is an Anthropic-specific request schema type ChatRequest struct { - Model string `json:"model"` - Messages []ChatMessage `json:"messages"` - System string `json:"system,omitempty"` - Temperature float64 `json:"temperature,omitempty"` - TopP float64 `json:"top_p,omitempty"` - TopK int `json:"top_k,omitempty"` - MaxTokens int `json:"max_tokens,omitempty"` - Stream bool `json:"stream,omitempty"` - Metadata *string `json:"metadata,omitempty"` - StopSequences []string `json:"stop_sequences,omitempty"` + Model string `json:"model"` + Messages []schemas.ChatMessage `json:"messages"` + System string `json:"system,omitempty"` + Temperature float64 `json:"temperature,omitempty"` + TopP float64 `json:"top_p,omitempty"` + TopK int `json:"top_k,omitempty"` + MaxTokens int `json:"max_tokens,omitempty"` + Stream bool `json:"stream,omitempty"` + Metadata *string `json:"metadata,omitempty"` + StopSequences []string `json:"stop_sequences,omitempty"` +} + +func (r *ChatRequest) ApplyParams(params *schemas.ChatParams) { + r.Messages = params.Messages } // NewChatRequestFromConfig fills the struct from the config. Not using reflection because of performance penalty it gives func NewChatRequestFromConfig(cfg *Config) *ChatRequest { return &ChatRequest{ - Model: cfg.Model, + Model: cfg.ModelName, System: cfg.DefaultParams.System, Temperature: cfg.DefaultParams.Temperature, TopP: cfg.DefaultParams.TopP, @@ -47,27 +48,18 @@ func NewChatRequestFromConfig(cfg *Config) *ChatRequest { } } -func NewChatMessagesFromUnifiedRequest(request *schemas.ChatRequest) []ChatMessage { - messages := make([]ChatMessage, 0, len(request.MessageHistory)+1) - - // Add items from messageHistory first and the new chat message last - for _, message := range request.MessageHistory { - messages = append(messages, ChatMessage{Role: message.Role, Content: message.Content}) - } - - messages = append(messages, ChatMessage{Role: request.Message.Role, Content: request.Message.Content}) - - return messages -} - // Chat sends a chat request to the specified anthropic model. // // Ref: https://docs.anthropic.com/claude/reference/messages_post -func (c *Client) Chat(ctx context.Context, request *schemas.ChatRequest) (*schemas.ChatResponse, error) { +func (c *Client) Chat(ctx context.Context, params *schemas.ChatParams) (*schemas.ChatResponse, error) { // Create a new chat request - chatRequest := c.createChatRequestSchema(request) + // TODO: consider using objectpool to optimize memory allocation + chatReq := *c.chatRequestTemplate + chatReq.ApplyParams(params) + + chatReq.Stream = false - chatResponse, err := c.doChatRequest(ctx, chatRequest) + chatResponse, err := c.doChatRequest(ctx, &chatReq) if err != nil { return nil, err } @@ -75,14 +67,6 @@ func (c *Client) Chat(ctx context.Context, request *schemas.ChatRequest) (*schem return chatResponse, nil } -func (c *Client) createChatRequestSchema(request *schemas.ChatRequest) *ChatRequest { - // TODO: consider using objectpool to optimize memory allocation - chatRequest := c.chatRequestTemplate // hoping to get a copy of the template - chatRequest.Messages = NewChatMessagesFromUnifiedRequest(request) - - return chatRequest -} - func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*schemas.ChatResponse, error) { // Build request payload rawPayload, err := json.Marshal(payload) @@ -134,10 +118,15 @@ func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*sche } if len(anthropicResponse.Content) == 0 { - return nil, ErrEmptyResponse + return nil, clients.ErrEmptyResponse } completion := anthropicResponse.Content[0] + + if len(completion.Text) == 0 { + return nil, clients.ErrEmptyResponse + } + usage := anthropicResponse.Usage // Map response to ChatResponse schema @@ -148,7 +137,7 @@ func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*sche ModelName: anthropicResponse.Model, Cached: false, ModelResponse: schemas.ModelResponse{ - SystemID: map[string]string{}, + Metadata: map[string]string{}, Message: schemas.ChatMessage{ Role: completion.Type, Content: completion.Text, diff --git a/pkg/providers/anthropic/chat_stream.go b/pkg/providers/anthropic/chat_stream.go index d5a31bc0..5a6f2112 100644 --- a/pkg/providers/anthropic/chat_stream.go +++ b/pkg/providers/anthropic/chat_stream.go @@ -3,14 +3,15 @@ package anthropic import ( "context" - "glide/pkg/api/schemas" - "glide/pkg/providers/clients" + "github.com/EinStack/glide/pkg/providers/clients" + + "github.com/EinStack/glide/pkg/api/schemas" ) func (c *Client) SupportChatStream() bool { return false } -func (c *Client) ChatStream(_ context.Context, _ *schemas.ChatStreamRequest) (clients.ChatStream, error) { +func (c *Client) ChatStream(_ context.Context, _ *schemas.ChatParams) (clients.ChatStream, error) { return nil, clients.ErrChatStreamNotImplemented } diff --git a/pkg/providers/anthropic/client.go b/pkg/providers/anthropic/client.go index 1af21262..bb34fe07 100644 --- a/pkg/providers/anthropic/client.go +++ b/pkg/providers/anthropic/client.go @@ -1,23 +1,19 @@ package anthropic import ( - "errors" "net/http" "net/url" + "time" - "glide/pkg/providers/clients" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/providers/clients" ) const ( providerName = "anthropic" ) -// ErrEmptyResponse is returned when the OpenAI API returns an empty response. -var ( - ErrEmptyResponse = errors.New("empty response") -) - // Client is a client for accessing OpenAI API type Client struct { baseURL string @@ -45,11 +41,10 @@ func NewClient(providerConfig *Config, clientConfig *clients.ClientConfig, tel * chatRequestTemplate: NewChatRequestFromConfig(providerConfig), errMapper: NewErrorMapper(tel), httpClient: &http.Client{ - Timeout: *clientConfig.Timeout, - // TODO: use values from the config + Timeout: time.Duration(*clientConfig.Timeout), Transport: &http.Transport{ - MaxIdleConns: 100, - MaxIdleConnsPerHost: 2, + MaxIdleConns: *clientConfig.MaxIdleConns, + MaxIdleConnsPerHost: *clientConfig.MaxIdleConnsPerHost, }, }, tel: tel, @@ -61,3 +56,7 @@ func NewClient(providerConfig *Config, clientConfig *clients.ClientConfig, tel * func (c *Client) Provider() string { return providerName } + +func (c *Client) ModelName() string { + return c.config.ModelName +} diff --git a/pkg/providers/anthropic/client_test.go b/pkg/providers/anthropic/client_test.go index 9c301365..b0c11f36 100644 --- a/pkg/providers/anthropic/client_test.go +++ b/pkg/providers/anthropic/client_test.go @@ -10,11 +10,11 @@ import ( "path/filepath" "testing" - "glide/pkg/providers/clients" + "github.com/EinStack/glide/pkg/providers/clients" - "glide/pkg/api/schemas" + "github.com/EinStack/glide/pkg/api/schemas" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" "github.com/stretchr/testify/require" ) @@ -56,12 +56,12 @@ func TestAnthropicClient_ChatRequest(t *testing.T) { client, err := NewClient(providerCfg, clientCfg, telemetry.NewTelemetryMock()) require.NoError(t, err) - request := schemas.ChatRequest{Message: schemas.ChatMessage{ + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ Role: "human", Content: "What's the biggest animal?", - }} + }}} - response, err := client.Chat(ctx, &request) + response, err := client.Chat(ctx, &chatParams) require.NoError(t, err) require.Equal(t, "msg_013Zva2CMHLNnXjNJJKqJ2EF", response.ID) @@ -86,12 +86,12 @@ func TestAnthropicClient_BadChatRequest(t *testing.T) { client, err := NewClient(providerCfg, clientCfg, telemetry.NewTelemetryMock()) require.NoError(t, err) - request := schemas.ChatRequest{Message: schemas.ChatMessage{ + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ Role: "human", Content: "What's the biggest animal?", - }} + }}} - response, err := client.Chat(ctx, &request) + response, err := client.Chat(ctx, &chatParams) // Assert that an error is returned require.Error(t, err) diff --git a/pkg/providers/anthropic/config.go b/pkg/providers/anthropic/config.go index 0de765ac..abdb5b73 100644 --- a/pkg/providers/anthropic/config.go +++ b/pkg/providers/anthropic/config.go @@ -1,7 +1,7 @@ package anthropic import ( - "glide/pkg/config/fields" + "github.com/EinStack/glide/pkg/config/fields" ) // Params defines OpenAI-specific model params with the specific validation of values @@ -36,12 +36,12 @@ func (p *Params) UnmarshalYAML(unmarshal func(interface{}) error) error { } type Config struct { - BaseURL string `yaml:"baseUrl" json:"baseUrl" validate:"required"` - APIVersion string `yaml:"apiVersion" json:"apiVersion" validate:"required"` - ChatEndpoint string `yaml:"chatEndpoint" json:"chatEndpoint" validate:"required"` - Model string `yaml:"model" json:"model" validate:"required"` + BaseURL string `yaml:"base_url" json:"base_url" validate:"required"` + APIVersion string `yaml:"api_version" json:"api_version" validate:"required"` + ChatEndpoint string `yaml:"chat_endpoint" json:"chat_endpoint" validate:"required"` + ModelName string `yaml:"model" json:"model" validate:"required"` APIKey fields.Secret `yaml:"api_key" json:"-" validate:"required"` - DefaultParams *Params `yaml:"defaultParams,omitempty" json:"defaultParams"` + DefaultParams *Params `yaml:"default_params,omitempty" json:"default_params"` } // DefaultConfig for OpenAI models @@ -52,7 +52,7 @@ func DefaultConfig() *Config { BaseURL: "https://api.anthropic.com/v1", APIVersion: "2023-06-01", ChatEndpoint: "/messages", - Model: "claude-instant-1.2", + ModelName: "claude-instant-1.2", DefaultParams: &defaultParams, } } diff --git a/pkg/providers/anthropic/errors.go b/pkg/providers/anthropic/errors.go index 44016560..126de68d 100644 --- a/pkg/providers/anthropic/errors.go +++ b/pkg/providers/anthropic/errors.go @@ -6,8 +6,9 @@ import ( "net/http" "time" - "glide/pkg/providers/clients" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/providers/clients" "go.uber.org/zap" ) diff --git a/pkg/providers/azureopenai/chat.go b/pkg/providers/azureopenai/chat.go index b3563eb2..22005fa3 100644 --- a/pkg/providers/azureopenai/chat.go +++ b/pkg/providers/azureopenai/chat.go @@ -8,8 +8,11 @@ import ( "io" "net/http" - "glide/pkg/api/schemas" - "glide/pkg/providers/openai" + "github.com/EinStack/glide/pkg/providers/clients" + + "github.com/EinStack/glide/pkg/providers/openai" + + "github.com/EinStack/glide/pkg/api/schemas" "go.uber.org/zap" ) @@ -35,39 +38,22 @@ func NewChatRequestFromConfig(cfg *Config) *ChatRequest { } // Chat sends a chat request to the specified azure openai model. -func (c *Client) Chat(ctx context.Context, request *schemas.ChatRequest) (*schemas.ChatResponse, error) { +func (c *Client) Chat(ctx context.Context, params *schemas.ChatParams) (*schemas.ChatResponse, error) { // Create a new chat request - chatRequest := c.createRequestSchema(request) + // TODO: consider using objectpool to optimize memory allocation + chatReq := *c.chatRequestTemplate // hoping to get a copy of the template + chatReq.ApplyParams(params) - chatResponse, err := c.doChatRequest(ctx, chatRequest) + chatReq.Stream = false + + chatResponse, err := c.doChatRequest(ctx, &chatReq) if err != nil { return nil, err } - if len(chatResponse.ModelResponse.Message.Content) == 0 { - return nil, ErrEmptyResponse - } - return chatResponse, nil } -// createRequestSchema creates a new ChatRequest object based on the given request. -func (c *Client) createRequestSchema(request *schemas.ChatRequest) *ChatRequest { - // TODO: consider using objectpool to optimize memory allocation - chatRequest := *c.chatRequestTemplate // hoping to get a copy of the template - - chatRequest.Messages = make([]ChatMessage, 0, len(request.MessageHistory)+1) - - // Add items from messageHistory first and the new chat message last - for _, message := range request.MessageHistory { - chatRequest.Messages = append(chatRequest.Messages, ChatMessage{Role: message.Role, Content: message.Content}) - } - - chatRequest.Messages = append(chatRequest.Messages, ChatMessage{Role: request.Message.Role, Content: request.Message.Content}) - - return &chatRequest -} - func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*schemas.ChatResponse, error) { // Build request payload rawPayload, err := json.Marshal(payload) @@ -109,35 +95,37 @@ func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*sche } // Parse the response JSON - var openAICompletion openai.ChatCompletion + var chatCompletion openai.ChatCompletion - err = json.Unmarshal(bodyBytes, &openAICompletion) + err = json.Unmarshal(bodyBytes, &chatCompletion) if err != nil { c.tel.Logger.Error("failed to parse openai chat response", zap.Error(err)) return nil, err } - openAICompletion.SystemFingerprint = "" // Azure OpenAI doesn't return this + modelChoice := chatCompletion.Choices[0] + + if len(modelChoice.Message.Content) == 0 { + return nil, clients.ErrEmptyResponse + } // Map response to UnifiedChatResponse schema response := schemas.ChatResponse{ - ID: openAICompletion.ID, - Created: openAICompletion.Created, + ID: chatCompletion.ID, + Created: chatCompletion.Created, Provider: providerName, - ModelName: openAICompletion.ModelName, + ModelName: chatCompletion.ModelName, Cached: false, ModelResponse: schemas.ModelResponse{ - SystemID: map[string]string{ - "system_fingerprint": openAICompletion.SystemFingerprint, - }, + Metadata: map[string]string{}, Message: schemas.ChatMessage{ - Role: openAICompletion.Choices[0].Message.Role, - Content: openAICompletion.Choices[0].Message.Content, + Role: modelChoice.Message.Role, + Content: modelChoice.Message.Content, }, TokenUsage: schemas.TokenUsage{ - PromptTokens: openAICompletion.Usage.PromptTokens, - ResponseTokens: openAICompletion.Usage.CompletionTokens, - TotalTokens: openAICompletion.Usage.TotalTokens, + PromptTokens: chatCompletion.Usage.PromptTokens, + ResponseTokens: chatCompletion.Usage.CompletionTokens, + TotalTokens: chatCompletion.Usage.TotalTokens, }, }, } diff --git a/pkg/providers/azureopenai/chat_stream.go b/pkg/providers/azureopenai/chat_stream.go index 6d44345d..8e73a556 100644 --- a/pkg/providers/azureopenai/chat_stream.go +++ b/pkg/providers/azureopenai/chat_stream.go @@ -8,14 +8,16 @@ import ( "io" "net/http" + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/providers/openai" + + "github.com/EinStack/glide/pkg/providers/clients" "github.com/r3labs/sse/v2" - "glide/pkg/providers/clients" - "glide/pkg/providers/openai" - "glide/pkg/telemetry" "go.uber.org/zap" - "glide/pkg/api/schemas" + "github.com/EinStack/glide/pkg/api/schemas" ) // TODO: Think about reducing the number of copy-pasted code btw OpenAI and Azure providers @@ -153,9 +155,9 @@ func (c *Client) SupportChatStream() bool { return true } -func (c *Client) ChatStream(ctx context.Context, req *schemas.ChatStreamRequest) (clients.ChatStream, error) { +func (c *Client) ChatStream(ctx context.Context, params *schemas.ChatParams) (clients.ChatStream, error) { // Create a new chat request - httpRequest, err := c.makeStreamReq(ctx, req) + httpRequest, err := c.makeStreamReq(ctx, params) if err != nil { return nil, err } @@ -169,28 +171,13 @@ func (c *Client) ChatStream(ctx context.Context, req *schemas.ChatStreamRequest) ), nil } -func (c *Client) createRequestFromStream(request *schemas.ChatStreamRequest) *ChatRequest { - // TODO: consider using objectpool to optimize memory allocation - chatRequest := *c.chatRequestTemplate // hoping to get a copy of the template - - chatRequest.Messages = make([]ChatMessage, 0, len(request.MessageHistory)+1) - - // Add items from messageHistory first and the new chat message last - for _, message := range request.MessageHistory { - chatRequest.Messages = append(chatRequest.Messages, ChatMessage{Role: message.Role, Content: message.Content}) - } - - chatRequest.Messages = append(chatRequest.Messages, ChatMessage{Role: request.Message.Role, Content: request.Message.Content}) - - return &chatRequest -} - -func (c *Client) makeStreamReq(ctx context.Context, req *schemas.ChatStreamRequest) (*http.Request, error) { - chatRequest := c.createRequestFromStream(req) +func (c *Client) makeStreamReq(ctx context.Context, params *schemas.ChatParams) (*http.Request, error) { + chatReq := *c.chatRequestTemplate + chatReq.ApplyParams(params) - chatRequest.Stream = true + chatReq.Stream = true - rawPayload, err := json.Marshal(chatRequest) + rawPayload, err := json.Marshal(chatReq) if err != nil { return nil, fmt.Errorf("unable to marshal AzureOpenAI chat stream request payload: %w", err) } @@ -210,7 +197,7 @@ func (c *Client) makeStreamReq(ctx context.Context, req *schemas.ChatStreamReque c.tel.L().Debug( "Stream chat request", zap.String("chatURL", c.chatURL), - zap.Any("payload", chatRequest), + zap.Any("payload", chatReq), ) return request, nil diff --git a/pkg/providers/azureopenai/chat_stream_test.go b/pkg/providers/azureopenai/chat_stream_test.go index 080ffb24..5aade1f5 100644 --- a/pkg/providers/azureopenai/chat_stream_test.go +++ b/pkg/providers/azureopenai/chat_stream_test.go @@ -10,10 +10,11 @@ import ( "path/filepath" "testing" - "glide/pkg/api/schemas" + "github.com/EinStack/glide/pkg/api/schemas" - "glide/pkg/providers/clients" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/providers/clients" "github.com/stretchr/testify/require" ) @@ -70,8 +71,12 @@ func TestAzureOpenAIClient_ChatStreamRequest(t *testing.T) { client, err := NewClient(providerCfg, clientCfg, telemetry.NewTelemetryMock()) require.NoError(t, err) - req := schemas.NewChatStreamFromStr("What's the capital of the United Kingdom?") - stream, err := client.ChatStream(ctx, req) + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ + Role: "user", + Content: "What's the capital of the United Kingdom?", + }}} + + stream, err := client.ChatStream(ctx, &chatParams) require.NoError(t, err) err = stream.Open() @@ -134,9 +139,12 @@ func TestAzureOpenAIClient_ChatStreamRequestInterrupted(t *testing.T) { client, err := NewClient(providerCfg, clientCfg, telemetry.NewTelemetryMock()) require.NoError(t, err) - req := schemas.NewChatStreamFromStr("What's the capital of the United Kingdom?") + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ + Role: "user", + Content: "What's the biggest animal?", + }}} - stream, err := client.ChatStream(ctx, req) + stream, err := client.ChatStream(ctx, &chatParams) require.NoError(t, err) err = stream.Open() diff --git a/pkg/providers/azureopenai/client.go b/pkg/providers/azureopenai/client.go index 6fa26d88..0f594805 100644 --- a/pkg/providers/azureopenai/client.go +++ b/pkg/providers/azureopenai/client.go @@ -1,25 +1,21 @@ package azureopenai import ( - "errors" "fmt" "net/http" + "time" - "glide/pkg/providers/openai" + "github.com/EinStack/glide/pkg/providers/openai" - "glide/pkg/providers/clients" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/providers/clients" ) const ( providerName = "azureopenai" ) -// ErrEmptyResponse is returned when the OpenAI API returns an empty response. -var ( - ErrEmptyResponse = errors.New("empty response") -) - // Client is a client for accessing Azure OpenAI API type Client struct { baseURL string // The name of your Azure OpenAI Resource (e.g https://glide-test.openai.azure.com/) @@ -37,7 +33,7 @@ func NewClient(providerConfig *Config, clientConfig *clients.ClientConfig, tel * chatURL := fmt.Sprintf( "%s/openai/deployments/%s/chat/completions?api-version=%s", providerConfig.BaseURL, - providerConfig.Model, + providerConfig.ModelName, providerConfig.APIVersion, ) @@ -49,11 +45,10 @@ func NewClient(providerConfig *Config, clientConfig *clients.ClientConfig, tel * finishReasonMapper: openai.NewFinishReasonMapper(tel), errMapper: NewErrorMapper(tel), httpClient: &http.Client{ - // TODO: use values from the config - Timeout: *clientConfig.Timeout, + Timeout: time.Duration(*clientConfig.Timeout), Transport: &http.Transport{ - MaxIdleConns: 100, - MaxIdleConnsPerHost: 2, + MaxIdleConns: *clientConfig.MaxIdleConns, + MaxIdleConnsPerHost: *clientConfig.MaxIdleConnsPerHost, }, }, tel: tel, @@ -65,3 +60,7 @@ func NewClient(providerConfig *Config, clientConfig *clients.ClientConfig, tel * func (c *Client) Provider() string { return providerName } + +func (c *Client) ModelName() string { + return c.config.ModelName +} diff --git a/pkg/providers/azureopenai/client_test.go b/pkg/providers/azureopenai/client_test.go index be98c316..1700bca0 100644 --- a/pkg/providers/azureopenai/client_test.go +++ b/pkg/providers/azureopenai/client_test.go @@ -10,11 +10,11 @@ import ( "path/filepath" "testing" - "glide/pkg/providers/clients" + "github.com/EinStack/glide/pkg/providers/clients" - "glide/pkg/api/schemas" + "github.com/EinStack/glide/pkg/api/schemas" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" "github.com/stretchr/testify/require" ) @@ -55,12 +55,12 @@ func TestAzureOpenAIClient_ChatRequest(t *testing.T) { client, err := NewClient(providerCfg, clientCfg, telemetry.NewTelemetryMock()) require.NoError(t, err) - request := schemas.ChatRequest{Message: schemas.ChatMessage{ + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ Role: "user", - Content: "What's the biggest animal?", - }} + Content: "What's the capital of the United Kingdom?", + }}} - response, err := client.Chat(ctx, &request) + response, err := client.Chat(ctx, &chatParams) require.NoError(t, err) require.Equal(t, "chatcmpl-8cdqrFT2lBQlHz0EDvvq6oQcRxNcZ", response.ID) @@ -81,19 +81,19 @@ func TestAzureOpenAIClient_ChatError(t *testing.T) { // Verify the default configuration values require.Equal(t, "/chat/completions", providerCfg.ChatEndpoint) - require.Equal(t, "", providerCfg.Model) + require.Equal(t, "", providerCfg.ModelName) require.Equal(t, "2023-05-15", providerCfg.APIVersion) require.NotNil(t, providerCfg.DefaultParams) client, err := NewClient(providerCfg, clientCfg, telemetry.NewTelemetryMock()) require.NoError(t, err) - request := schemas.ChatRequest{Message: schemas.ChatMessage{ - Role: "user", + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ + Role: "human", Content: "What's the biggest animal?", - }} + }}} - response, err := client.Chat(ctx, &request) + response, err := client.Chat(ctx, &chatParams) require.Error(t, err) require.Nil(t, response) } @@ -115,10 +115,12 @@ func TestDoChatRequest_ErrorResponse(t *testing.T) { client, err := NewClient(providerCfg, clientCfg, telemetry.NewTelemetryMock()) require.NoError(t, err) - // Create a chat request payload - payload := schemas.NewChatFromStr("What's the dealio?") + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ + Role: "user", + Content: "What's the dealio?", + }}} - _, err = client.Chat(ctx, payload) + _, err = client.Chat(ctx, &chatParams) require.Error(t, err) require.Contains(t, err.Error(), "provider is not available") diff --git a/pkg/providers/azureopenai/config.go b/pkg/providers/azureopenai/config.go index 29e2e978..5ae5ea33 100644 --- a/pkg/providers/azureopenai/config.go +++ b/pkg/providers/azureopenai/config.go @@ -1,7 +1,7 @@ package azureopenai import ( - "glide/pkg/config/fields" + "github.com/EinStack/glide/pkg/config/fields" ) // Params defines OpenAI-specific model params with the specific validation of values @@ -20,7 +20,6 @@ type Params struct { Tools []string `yaml:"tools,omitempty" json:"tools"` ToolChoice interface{} `yaml:"tool_choice,omitempty" json:"tool_choice"` ResponseFormat interface{} `yaml:"response_format,omitempty" json:"response_format"` // TODO: should this be a part of the chat request API? - // Stream bool `json:"stream,omitempty"` // TODO: we are not supporting this at the moment } func DefaultParams() Params { @@ -43,12 +42,12 @@ func (p *Params) UnmarshalYAML(unmarshal func(interface{}) error) error { } type Config struct { - BaseURL string `yaml:"base_url" json:"baseUrl" validate:"required"` // The name of your Azure OpenAI Resource (e.g https://glide-test.openai.azure.com/) - ChatEndpoint string `yaml:"chat_endpoint" json:"chatEndpoint"` - Model string `yaml:"model" json:"model" validate:"required"` // This is your deployment name. You're required to first deploy a model before you can make calls (e.g. glide-gpt-35) + BaseURL string `yaml:"base_url" json:"base_url" validate:"required"` // The name of your Azure OpenAI Resource (e.g https://glide-test.openai.azure.com/) + ChatEndpoint string `yaml:"chat_endpoint" json:"chat_endpoint"` + ModelName string `yaml:"model" json:"model" validate:"required"` // This is your deployment name. You're required to first deploy a model before you can make calls (e.g. glide-gpt-35) APIVersion string `yaml:"api_version" json:"apiVersion" validate:"required"` // The API version to use for this operation. This follows the YYYY-MM-DD format (e.g 2023-05-15) APIKey fields.Secret `yaml:"api_key" json:"-" validate:"required"` - DefaultParams *Params `yaml:"default_params,omitempty" json:"defaultParams"` + DefaultParams *Params `yaml:"default_params,omitempty" json:"default_params"` } // DefaultConfig for OpenAI models @@ -58,7 +57,7 @@ func DefaultConfig() *Config { return &Config{ BaseURL: "", // This needs to come from config ChatEndpoint: "/chat/completions", - Model: "", // This needs to come from config + ModelName: "", // This needs to come from config APIVersion: "2023-05-15", DefaultParams: &defaultParams, } diff --git a/pkg/providers/azureopenai/errors.go b/pkg/providers/azureopenai/errors.go index 0e55c0b0..6a30e989 100644 --- a/pkg/providers/azureopenai/errors.go +++ b/pkg/providers/azureopenai/errors.go @@ -6,8 +6,9 @@ import ( "net/http" "time" - "glide/pkg/providers/clients" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/providers/clients" "go.uber.org/zap" ) diff --git a/pkg/providers/azureopenai/schemas.go b/pkg/providers/azureopenai/schemas.go index 993bb8d7..5940648c 100644 --- a/pkg/providers/azureopenai/schemas.go +++ b/pkg/providers/azureopenai/schemas.go @@ -1,27 +1,28 @@ package azureopenai -type ChatMessage struct { - Role string `json:"role"` - Content string `json:"content"` -} +import "github.com/EinStack/glide/pkg/api/schemas" // ChatRequest is an Azure openai-specific request schema type ChatRequest struct { - Messages []ChatMessage `json:"messages"` - Temperature float64 `json:"temperature,omitempty"` - TopP float64 `json:"top_p,omitempty"` - MaxTokens int `json:"max_tokens,omitempty"` - N int `json:"n,omitempty"` - StopWords []string `json:"stop,omitempty"` - Stream bool `json:"stream,omitempty"` - FrequencyPenalty int `json:"frequency_penalty,omitempty"` - PresencePenalty int `json:"presence_penalty,omitempty"` - LogitBias *map[int]float64 `json:"logit_bias,omitempty"` - User *string `json:"user,omitempty"` - Seed *int `json:"seed,omitempty"` - Tools []string `json:"tools,omitempty"` - ToolChoice interface{} `json:"tool_choice,omitempty"` - ResponseFormat interface{} `json:"response_format,omitempty"` + Messages []schemas.ChatMessage `json:"messages"` + Temperature float64 `json:"temperature,omitempty"` + TopP float64 `json:"top_p,omitempty"` + MaxTokens int `json:"max_tokens,omitempty"` + N int `json:"n,omitempty"` + StopWords []string `json:"stop,omitempty"` + Stream bool `json:"stream,omitempty"` + FrequencyPenalty int `json:"frequency_penalty,omitempty"` + PresencePenalty int `json:"presence_penalty,omitempty"` + LogitBias *map[int]float64 `json:"logit_bias,omitempty"` + User *string `json:"user,omitempty"` + Seed *int `json:"seed,omitempty"` + Tools []string `json:"tools,omitempty"` + ToolChoice interface{} `json:"tool_choice,omitempty"` + ResponseFormat interface{} `json:"response_format,omitempty"` +} + +func (r *ChatRequest) ApplyParams(params *schemas.ChatParams) { + r.Messages = params.Messages } // ChatCompletion @@ -37,10 +38,10 @@ type ChatCompletion struct { } type Choice struct { - Index int `json:"index"` - Message ChatMessage `json:"message"` - Logprobs interface{} `json:"logprobs"` - FinishReason string `json:"finish_reason"` + Index int `json:"index"` + Message schemas.ChatMessage `json:"message"` + Logprobs interface{} `json:"logprobs"` + FinishReason string `json:"finish_reason"` } type Usage struct { @@ -61,7 +62,7 @@ type ChatCompletionChunk struct { } type StreamChoice struct { - Index int `json:"index"` - Delta ChatMessage `json:"delta"` - FinishReason string `json:"finish_reason"` + Index int `json:"index"` + Delta schemas.ChatMessage `json:"delta"` + FinishReason string `json:"finish_reason"` } diff --git a/pkg/providers/bedrock/chat.go b/pkg/providers/bedrock/chat.go index bb17cb11..658c1769 100644 --- a/pkg/providers/bedrock/chat.go +++ b/pkg/providers/bedrock/chat.go @@ -6,7 +6,7 @@ import ( "fmt" "time" - "glide/pkg/api/schemas" + "github.com/EinStack/glide/pkg/api/schemas" "go.uber.org/zap" @@ -16,17 +16,21 @@ import ( "github.com/aws/aws-sdk-go-v2/service/bedrockruntime" ) -type ChatMessage struct { - Role string `json:"role"` - Content string `json:"content"` -} - -// ChatRequest is an Bedrock-specific request schema +// ChatRequest is a Bedrock-specific request schema type ChatRequest struct { Messages string `json:"inputText"` TextGenerationConfig TextGenerationConfig `json:"textGenerationConfig"` } +func (r *ChatRequest) ApplyParams(params *schemas.ChatParams) { + // message history not yet supported for AWS models + // TODO: do something about lack of message history. Maybe just concatenate all messages? + // in any case, this is not a way to go to ignore message history + message := params.Messages[len(params.Messages)-1] + + r.Messages = fmt.Sprintf("Role: %s, Content: %s", message.Role, message.Content) +} + type TextGenerationConfig struct { Temperature float64 `json:"temperature"` TopP float64 `json:"topP"` @@ -46,38 +50,21 @@ func NewChatRequestFromConfig(cfg *Config) *ChatRequest { } } -func NewChatMessagesFromUnifiedRequest(request *schemas.ChatRequest) string { - // message history not yet supported for AWS models - message := fmt.Sprintf("Role: %s, Content: %s", request.Message.Role, request.Message.Content) - - return message -} - // Chat sends a chat request to the specified bedrock model. -func (c *Client) Chat(ctx context.Context, request *schemas.ChatRequest) (*schemas.ChatResponse, error) { +func (c *Client) Chat(ctx context.Context, params *schemas.ChatParams) (*schemas.ChatResponse, error) { // Create a new chat request - chatRequest := c.createChatRequestSchema(request) + // TODO: consider using objectpool to optimize memory allocation + chatReq := *c.chatRequestTemplate // hoping to get a copy of the template + chatReq.ApplyParams(params) - chatResponse, err := c.doChatRequest(ctx, chatRequest) + chatResponse, err := c.doChatRequest(ctx, &chatReq) if err != nil { return nil, err } - if len(chatResponse.ModelResponse.Message.Content) == 0 { - return nil, ErrEmptyResponse - } - return chatResponse, nil } -func (c *Client) createChatRequestSchema(request *schemas.ChatRequest) *ChatRequest { - // TODO: consider using objectpool to optimize memory allocation - chatRequest := c.chatRequestTemplate // hoping to get a copy of the template - chatRequest.Messages = NewChatMessagesFromUnifiedRequest(request) - - return chatRequest -} - func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*schemas.ChatResponse, error) { rawPayload, err := json.Marshal(payload) if err != nil { @@ -85,7 +72,7 @@ func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*sche } result, err := c.bedrockClient.InvokeModel(ctx, &bedrockruntime.InvokeModelInput{ - ModelId: aws.String(c.config.Model), + ModelId: aws.String(c.config.ModelName), ContentType: aws.String("application/json"), Body: rawPayload, }) @@ -103,25 +90,28 @@ func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*sche return nil, err } + modelResult := bedrockCompletion.Results[0] + + if len(modelResult.OutputText) == 0 { + return nil, ErrEmptyResponse + } + response := schemas.ChatResponse{ ID: uuid.NewString(), Created: int(time.Now().Unix()), - Provider: "aws-bedrock", - ModelName: c.config.Model, + Provider: providerName, + ModelName: c.config.ModelName, Cached: false, ModelResponse: schemas.ModelResponse{ - SystemID: map[string]string{ - "system_fingerprint": "none", - }, Message: schemas.ChatMessage{ Role: "assistant", - Content: bedrockCompletion.Results[0].OutputText, - Name: "", + Content: modelResult.OutputText, }, TokenUsage: schemas.TokenUsage{ - PromptTokens: bedrockCompletion.Results[0].TokenCount, + // TODO: what would happen if there is a few responses? We need to sum that up + PromptTokens: modelResult.TokenCount, ResponseTokens: -1, - TotalTokens: bedrockCompletion.Results[0].TokenCount, + TotalTokens: modelResult.TokenCount, }, }, } diff --git a/pkg/providers/bedrock/chat_stream.go b/pkg/providers/bedrock/chat_stream.go index 35918a0c..bb07da7d 100644 --- a/pkg/providers/bedrock/chat_stream.go +++ b/pkg/providers/bedrock/chat_stream.go @@ -3,14 +3,15 @@ package bedrock import ( "context" - "glide/pkg/api/schemas" - "glide/pkg/providers/clients" + "github.com/EinStack/glide/pkg/providers/clients" + + "github.com/EinStack/glide/pkg/api/schemas" ) func (c *Client) SupportChatStream() bool { return false } -func (c *Client) ChatStream(_ context.Context, _ *schemas.ChatStreamRequest) (clients.ChatStream, error) { +func (c *Client) ChatStream(_ context.Context, _ *schemas.ChatParams) (clients.ChatStream, error) { return nil, clients.ErrChatStreamNotImplemented } diff --git a/pkg/providers/bedrock/client.go b/pkg/providers/bedrock/client.go index 130d06a7..0567b9fc 100644 --- a/pkg/providers/bedrock/client.go +++ b/pkg/providers/bedrock/client.go @@ -5,9 +5,11 @@ import ( "errors" "net/http" "net/url" + "time" - "glide/pkg/providers/clients" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/providers/clients" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/credentials" @@ -15,7 +17,7 @@ import ( ) const ( - providerName = "bedrock" + providerName = "aws/bedrock" ) // ErrEmptyResponse is returned when the OpenAI API returns an empty response. @@ -36,7 +38,7 @@ type Client struct { // NewClient creates a new OpenAI client for the OpenAI API. func NewClient(providerConfig *Config, clientConfig *clients.ClientConfig, tel *telemetry.Telemetry) (*Client, error) { - chatURL, err := url.JoinPath(providerConfig.BaseURL, providerConfig.ChatEndpoint, providerConfig.Model, "/invoke") + chatURL, err := url.JoinPath(providerConfig.BaseURL, providerConfig.ChatEndpoint, providerConfig.ModelName, "/invoke") if err != nil { return nil, err } @@ -55,11 +57,10 @@ func NewClient(providerConfig *Config, clientConfig *clients.ClientConfig, tel * config: providerConfig, chatRequestTemplate: NewChatRequestFromConfig(providerConfig), httpClient: &http.Client{ - Timeout: *clientConfig.Timeout, - // TODO: use values from the config + Timeout: time.Duration(*clientConfig.Timeout), Transport: &http.Transport{ - MaxIdleConns: 100, - MaxIdleConnsPerHost: 2, + MaxIdleConns: *clientConfig.MaxIdleConns, + MaxIdleConnsPerHost: *clientConfig.MaxIdleConnsPerHost, }, }, telemetry: tel, @@ -71,3 +72,7 @@ func NewClient(providerConfig *Config, clientConfig *clients.ClientConfig, tel * func (c *Client) Provider() string { return providerName } + +func (c *Client) ModelName() string { + return c.config.ModelName +} diff --git a/pkg/providers/bedrock/client_test.go b/pkg/providers/bedrock/client_test.go index bcbd0fa1..cdae1f68 100644 --- a/pkg/providers/bedrock/client_test.go +++ b/pkg/providers/bedrock/client_test.go @@ -11,11 +11,11 @@ import ( "path/filepath" "testing" - "glide/pkg/providers/clients" + "github.com/EinStack/glide/pkg/providers/clients" - "glide/pkg/api/schemas" + "github.com/EinStack/glide/pkg/api/schemas" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" "github.com/stretchr/testify/require" ) @@ -61,12 +61,12 @@ func TestBedrockClient_ChatRequest(t *testing.T) { client, err := NewClient(providerCfg, clientCfg, telemetry.NewTelemetryMock()) require.NoError(t, err) - request := schemas.ChatRequest{Message: schemas.ChatMessage{ + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ Role: "user", Content: "What's the biggest animal?", - }} + }}} - response, err := client.Chat(ctx, &request) + response, err := client.Chat(ctx, &chatParams) responseString := fmt.Sprintf("%+v", response) // errString := fmt.Sprintf("%+v", err) diff --git a/pkg/providers/bedrock/config.go b/pkg/providers/bedrock/config.go index a5608ece..36ae6b3b 100644 --- a/pkg/providers/bedrock/config.go +++ b/pkg/providers/bedrock/config.go @@ -1,7 +1,7 @@ package bedrock import ( - "glide/pkg/config/fields" + "github.com/EinStack/glide/pkg/config/fields" ) // Params defines OpenAI-specific model params with the specific validation of values @@ -31,14 +31,14 @@ func (p *Params) UnmarshalYAML(unmarshal func(interface{}) error) error { } type Config struct { - BaseURL string `yaml:"baseUrl" json:"baseUrl" validate:"required"` - ChatEndpoint string `yaml:"chatEndpoint" json:"chatEndpoint" validate:"required"` - Model string `yaml:"model" json:"model" validate:"required"` + BaseURL string `yaml:"base_url" json:"base_url" validate:"required"` + ChatEndpoint string `yaml:"chat_endpoint" json:"chat_endpoint" validate:"required"` + ModelName string `yaml:"model" json:"model" validate:"required"` APIKey fields.Secret `yaml:"api_key" json:"-" validate:"required"` AccessKey string `yaml:"access_key" json:"-" validate:"required"` SecretKey string `yaml:"secret_key" json:"-" validate:"required"` AWSRegion string `yaml:"aws_region" json:"awsRegion" validate:"required"` - DefaultParams *Params `yaml:"defaultParams,omitempty" json:"defaultParams"` + DefaultParams *Params `yaml:"default_params,omitempty" json:"default_params"` } // DefaultConfig for OpenAI models @@ -48,7 +48,7 @@ func DefaultConfig() *Config { return &Config{ BaseURL: "", // This needs to come from config. https://bedrock-runtime.{{AWS_Region}}.amazonaws.com/ ChatEndpoint: "/model", - Model: "amazon.titan-text-express-v1", + ModelName: "amazon.titan-text-express-v1", DefaultParams: &defaultParams, } } diff --git a/pkg/providers/clients/config.go b/pkg/providers/clients/config.go index d01a2ab1..1dbea893 100644 --- a/pkg/providers/clients/config.go +++ b/pkg/providers/clients/config.go @@ -1,15 +1,25 @@ package clients -import "time" +import ( + "time" + + "github.com/EinStack/glide/pkg/config/fields" +) type ClientConfig struct { - Timeout *time.Duration `yaml:"timeout,omitempty" json:"timeout" swaggertype:"primitive,string"` + Timeout *fields.Duration `yaml:"timeout,omitempty" json:"timeout" swaggertype:"primitive,string"` + MaxIdleConns *int `yaml:"max_idle_connections,omitempty" json:"max_idle_connections" swaggertype:"primitive,integer"` + MaxIdleConnsPerHost *int `yaml:"max_idle_connections_per_host,omitempty" json:"max_idle_connections_per_host" swaggertype:"primitive,integer"` } func DefaultClientConfig() *ClientConfig { defaultTimeout := 10 * time.Second + maxIdleConns := 100 + maxIdleConnsPerHost := 2 return &ClientConfig{ - Timeout: &defaultTimeout, + Timeout: (*fields.Duration)(&defaultTimeout), + MaxIdleConns: &maxIdleConns, + MaxIdleConnsPerHost: &maxIdleConnsPerHost, } } diff --git a/pkg/providers/clients/config_test.go b/pkg/providers/clients/config_test.go index 0e725201..18bd91ad 100644 --- a/pkg/providers/clients/config_test.go +++ b/pkg/providers/clients/config_test.go @@ -1,9 +1,13 @@ package clients import ( + "encoding/json" "testing" + "time" "github.com/stretchr/testify/require" + + "github.com/EinStack/glide/pkg/config/fields" ) func TestClientConfig_DefaultConfig(t *testing.T) { @@ -11,3 +15,39 @@ func TestClientConfig_DefaultConfig(t *testing.T) { require.NotEmpty(t, config.Timeout) } + +func TestClientConfig_JSONMarshal(t *testing.T) { + defaultConfig := DefaultClientConfig() + + expectedJSON := `{ + "timeout": "10s", + "max_idle_connections": 100, + "max_idle_connections_per_host": 2 + }` + + marshaledJSON, err := json.MarshalIndent(defaultConfig, "", "\t") + + require.NoError(t, err) + require.JSONEq(t, expectedJSON, string(marshaledJSON)) +} + +func TestDefaultClientConfig(t *testing.T) { + config := DefaultClientConfig() + + require.NotNil(t, config, "Config must not be nil") + require.NotNil(t, config.Timeout, "Timeout must not be nil") + require.NotNil(t, config.MaxIdleConns, "MaxIdleConns must not be nil") + require.NotNil(t, config.MaxIdleConnsPerHost, "MaxIdleConnsPerHost must not be nil") + + // Check default timeout + expectedTimeout := fields.Duration(10 * time.Second) + require.Equal(t, expectedTimeout, *config.Timeout) + + // Check MaxIdleConns + expectedMaxIdleConns := 100 + require.Equal(t, expectedMaxIdleConns, *config.MaxIdleConns) + + // Check MaxIdleConnsPerHost + expectedMaxIdleConnsPerHost := 2 + require.Equal(t, expectedMaxIdleConnsPerHost, *config.MaxIdleConnsPerHost) +} diff --git a/pkg/providers/clients/errors.go b/pkg/providers/clients/errors.go index deaf00bc..2c243720 100644 --- a/pkg/providers/clients/errors.go +++ b/pkg/providers/clients/errors.go @@ -7,6 +7,7 @@ import ( ) var ( + ErrEmptyResponse = errors.New("empty model response") ErrProviderUnavailable = errors.New("provider is not available") ErrUnauthorized = errors.New("API key is wrong or not set") ErrChatStreamNotImplemented = errors.New("streaming chat API is not implemented for provider") diff --git a/pkg/providers/clients/stream.go b/pkg/providers/clients/stream.go index ff150e8f..913bbddc 100644 --- a/pkg/providers/clients/stream.go +++ b/pkg/providers/clients/stream.go @@ -1,7 +1,7 @@ package clients import ( - "glide/pkg/api/schemas" + "github.com/EinStack/glide/pkg/api/schemas" ) type ChatStream interface { diff --git a/pkg/providers/cohere/chat.go b/pkg/providers/cohere/chat.go index beb6403c..ddf75680 100644 --- a/pkg/providers/cohere/chat.go +++ b/pkg/providers/cohere/chat.go @@ -9,16 +9,17 @@ import ( "net/http" "time" - "glide/pkg/providers/clients" + "github.com/EinStack/glide/pkg/providers/clients" + + "github.com/EinStack/glide/pkg/api/schemas" - "glide/pkg/api/schemas" "go.uber.org/zap" ) // NewChatRequestFromConfig fills the struct from the config. Not using reflection because of performance penalty it gives func NewChatRequestFromConfig(cfg *Config) *ChatRequest { return &ChatRequest{ - Model: cfg.Model, + Model: cfg.ModelName, Temperature: cfg.DefaultParams.Temperature, Preamble: cfg.DefaultParams.Preamble, PromptTruncation: cfg.DefaultParams.PromptTruncation, @@ -29,45 +30,20 @@ func NewChatRequestFromConfig(cfg *Config) *ChatRequest { } // Chat sends a chat request to the specified cohere model. -func (c *Client) Chat(ctx context.Context, request *schemas.ChatRequest) (*schemas.ChatResponse, error) { +func (c *Client) Chat(ctx context.Context, params *schemas.ChatParams) (*schemas.ChatResponse, error) { // Create a new chat request - chatRequest := c.createRequestSchema(request) + // TODO: consider using objectpool to optimize memory allocation + chatReq := *c.chatRequestTemplate + chatReq.ApplyParams(params) - chatResponse, err := c.doChatRequest(ctx, chatRequest) + chatResponse, err := c.doChatRequest(ctx, &chatReq) if err != nil { return nil, err } - if len(chatResponse.ModelResponse.Message.Content) == 0 { - return nil, ErrEmptyResponse - } - return chatResponse, nil } -func (c *Client) createRequestSchema(request *schemas.ChatRequest) *ChatRequest { - // TODO: consider using objectpool to optimize memory allocation - chatRequest := *c.chatRequestTemplate // hoping to get a copy of the template - chatRequest.Message = request.Message.Content - - // Build the Cohere specific ChatHistory - if len(request.MessageHistory) > 0 { - chatRequest.ChatHistory = make([]ChatMessage, 0, len(request.MessageHistory)) - - for _, message := range request.MessageHistory { - chatRequest.ChatHistory = append( - chatRequest.ChatHistory, - ChatMessage{ - Role: message.Role, - Content: message.Content, - }, - ) - } - } - - return &chatRequest -} - func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*schemas.ChatResponse, error) { // Build request payload rawPayload, err := json.Marshal(payload) @@ -134,22 +110,25 @@ func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*sche return nil, err } + if len(cohereCompletion.Text) == 0 { + return nil, clients.ErrEmptyResponse + } + // Map response to ChatResponse schema response := schemas.ChatResponse{ ID: cohereCompletion.ResponseID, Created: int(time.Now().UTC().Unix()), // Cohere doesn't provide this Provider: providerName, - ModelName: c.config.Model, + ModelName: c.config.ModelName, Cached: false, ModelResponse: schemas.ModelResponse{ - SystemID: map[string]string{ + Metadata: map[string]string{ "generationId": cohereCompletion.GenerationID, "responseId": cohereCompletion.ResponseID, }, Message: schemas.ChatMessage{ - Role: "model", + Role: "assistant", Content: cohereCompletion.Text, - Name: "", }, TokenUsage: schemas.TokenUsage{ PromptTokens: cohereCompletion.TokenCount.PromptTokens, diff --git a/pkg/providers/cohere/chat_stream.go b/pkg/providers/cohere/chat_stream.go index aeb3cbec..1d8ed243 100644 --- a/pkg/providers/cohere/chat_stream.go +++ b/pkg/providers/cohere/chat_stream.go @@ -8,12 +8,13 @@ import ( "io" "net/http" - "glide/pkg/providers/clients" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/providers/clients" "go.uber.org/zap" - "glide/pkg/api/schemas" + "github.com/EinStack/glide/pkg/api/schemas" ) // SupportedEventType Cohere has other types too: @@ -177,9 +178,9 @@ func (c *Client) SupportChatStream() bool { return true } -func (c *Client) ChatStream(ctx context.Context, req *schemas.ChatStreamRequest) (clients.ChatStream, error) { +func (c *Client) ChatStream(ctx context.Context, params *schemas.ChatParams) (clients.ChatStream, error) { // Create a new chat request - httpRequest, err := c.makeStreamReq(ctx, req) + httpRequest, err := c.makeStreamReq(ctx, params) if err != nil { return nil, err } @@ -194,35 +195,14 @@ func (c *Client) ChatStream(ctx context.Context, req *schemas.ChatStreamRequest) ), nil } -func (c *Client) createRequestFromStream(request *schemas.ChatStreamRequest) *ChatRequest { +func (c *Client) makeStreamReq(ctx context.Context, params *schemas.ChatParams) (*http.Request, error) { // TODO: consider using objectpool to optimize memory allocation - chatRequest := *c.chatRequestTemplate // hoping to get a copy of the template - chatRequest.Message = request.Message.Content - - // Build the Cohere specific ChatHistory - if len(request.MessageHistory) > 0 { - chatRequest.ChatHistory = make([]ChatMessage, 0, len(request.MessageHistory)) - - for _, message := range request.MessageHistory { - chatRequest.ChatHistory = append( - chatRequest.ChatHistory, - ChatMessage{ - Role: message.Role, - Content: message.Content, - }, - ) - } - } - - return &chatRequest -} - -func (c *Client) makeStreamReq(ctx context.Context, req *schemas.ChatStreamRequest) (*http.Request, error) { - chatRequest := c.createRequestFromStream(req) + chatReq := *c.chatRequestTemplate + chatReq.ApplyParams(params) - chatRequest.Stream = true + chatReq.Stream = true - rawPayload, err := json.Marshal(chatRequest) + rawPayload, err := json.Marshal(chatReq) if err != nil { return nil, fmt.Errorf("unable to marshal cohere chat stream request payload: %w", err) } @@ -242,7 +222,7 @@ func (c *Client) makeStreamReq(ctx context.Context, req *schemas.ChatStreamReque c.tel.L().Debug( "Stream chat request", zap.String("chatURL", c.chatURL), - zap.Any("payload", chatRequest), + zap.Any("payload", chatReq), ) return request, nil diff --git a/pkg/providers/cohere/chat_stream_test.go b/pkg/providers/cohere/chat_stream_test.go index c89e646c..7deb5b88 100644 --- a/pkg/providers/cohere/chat_stream_test.go +++ b/pkg/providers/cohere/chat_stream_test.go @@ -10,10 +10,11 @@ import ( "path/filepath" "testing" - "glide/pkg/api/schemas" + "github.com/EinStack/glide/pkg/api/schemas" - "glide/pkg/providers/clients" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/providers/clients" "github.com/stretchr/testify/require" ) @@ -70,9 +71,12 @@ func TestCohere_ChatStreamRequest(t *testing.T) { client, err := NewClient(providerCfg, clientCfg, telemetry.NewTelemetryMock()) require.NoError(t, err) - req := schemas.NewChatStreamFromStr("What's the capital of the United Kingdom?") + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ + Role: "user", + Content: "What's the capital of the United Kingdom?", + }}} - stream, err := client.ChatStream(ctx, req) + stream, err := client.ChatStream(ctx, &chatParams) require.NoError(t, err) err = stream.Open() @@ -134,8 +138,12 @@ func TestCohere_ChatStreamRequestInterrupted(t *testing.T) { client, err := NewClient(providerCfg, clientCfg, telemetry.NewTelemetryMock()) require.NoError(t, err) - req := schemas.NewChatStreamFromStr("What's the capital of the United Kingdom?") - stream, err := client.ChatStream(ctx, req) + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ + Role: "user", + Content: "What's the capital of the United Kingdom?", + }}} + + stream, err := client.ChatStream(ctx, &chatParams) require.NoError(t, err) err = stream.Open() diff --git a/pkg/providers/cohere/client.go b/pkg/providers/cohere/client.go index b266387a..c13ff64b 100644 --- a/pkg/providers/cohere/client.go +++ b/pkg/providers/cohere/client.go @@ -1,23 +1,19 @@ package cohere import ( - "errors" "net/http" "net/url" + "time" - "glide/pkg/providers/clients" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/providers/clients" ) const ( providerName = "cohere" ) -// ErrEmptyResponse is returned when the Cohere API returns an empty response. -var ( - ErrEmptyResponse = errors.New("empty response") -) - // Client is a client for accessing Cohere API type Client struct { baseURL string @@ -43,11 +39,10 @@ func NewClient(providerConfig *Config, clientConfig *clients.ClientConfig, tel * config: providerConfig, chatRequestTemplate: NewChatRequestFromConfig(providerConfig), httpClient: &http.Client{ - Timeout: *clientConfig.Timeout, - // TODO: use values from the config + Timeout: time.Duration(*clientConfig.Timeout), Transport: &http.Transport{ - MaxIdleConns: 100, - MaxIdleConnsPerHost: 2, + MaxIdleConns: *clientConfig.MaxIdleConns, + MaxIdleConnsPerHost: *clientConfig.MaxIdleConnsPerHost, }, }, errMapper: NewErrorMapper(tel), @@ -61,3 +56,7 @@ func NewClient(providerConfig *Config, clientConfig *clients.ClientConfig, tel * func (c *Client) Provider() string { return providerName } + +func (c *Client) ModelName() string { + return c.config.ModelName +} diff --git a/pkg/providers/cohere/client_test.go b/pkg/providers/cohere/client_test.go index 439e44d6..2e5ab487 100644 --- a/pkg/providers/cohere/client_test.go +++ b/pkg/providers/cohere/client_test.go @@ -11,11 +11,11 @@ import ( "path/filepath" "testing" - "glide/pkg/api/schemas" + "github.com/EinStack/glide/pkg/api/schemas" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" - "glide/pkg/providers/clients" + "github.com/EinStack/glide/pkg/providers/clients" "github.com/stretchr/testify/require" ) @@ -55,12 +55,12 @@ func TestCohereClient_ChatRequest(t *testing.T) { client, err := NewClient(providerCfg, clientCfg, telemetry.NewTelemetryMock()) require.NoError(t, err) - request := schemas.ChatRequest{Message: schemas.ChatMessage{ + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ Role: "human", Content: "What's the biggest animal?", - }} + }}} - response, err := client.Chat(ctx, &request) + response, err := client.Chat(ctx, &chatParams) require.NoError(t, err) require.Equal(t, "ec9eb88b-2da5-462e-8f0f-0899d243aa2e", response.ID) diff --git a/pkg/providers/cohere/config.go b/pkg/providers/cohere/config.go index 3688b7c1..8e7b8b1d 100644 --- a/pkg/providers/cohere/config.go +++ b/pkg/providers/cohere/config.go @@ -1,7 +1,7 @@ package cohere import ( - "glide/pkg/config/fields" + "github.com/EinStack/glide/pkg/config/fields" ) // Params defines Cohere-specific model params with the specific validation of values @@ -39,9 +39,9 @@ func (p *Params) UnmarshalYAML(unmarshal func(interface{}) error) error { } type Config struct { - BaseURL string `yaml:"base_url" json:"baseUrl" validate:"required,http_url"` - ChatEndpoint string `yaml:"chat_endpoint" json:"chatEndpoint" validate:"required"` - Model string `yaml:"model" json:"model" validate:"required"` // https://docs.cohere.com/docs/models#command + BaseURL string `yaml:"base_url" json:"base_url" validate:"required,http_url"` + ChatEndpoint string `yaml:"chat_endpoint" json:"chat_endpoint" validate:"required"` + ModelName string `yaml:"model" json:"model" validate:"required"` // https://docs.cohere.com/docs/models#command APIKey fields.Secret `yaml:"api_key" json:"-" validate:"required"` DefaultParams *Params `yaml:"default_params,omitempty" json:"defaultParams"` } @@ -53,7 +53,7 @@ func DefaultConfig() *Config { return &Config{ BaseURL: "https://api.cohere.ai/v1", ChatEndpoint: "/chat", - Model: "command-light", + ModelName: "command-light", DefaultParams: &defaultParams, } } diff --git a/pkg/providers/cohere/errors.go b/pkg/providers/cohere/errors.go index 3e5ae89e..118ef719 100644 --- a/pkg/providers/cohere/errors.go +++ b/pkg/providers/cohere/errors.go @@ -6,8 +6,9 @@ import ( "net/http" "time" - "glide/pkg/providers/clients" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/providers/clients" "go.uber.org/zap" ) diff --git a/pkg/providers/cohere/finish_reason.go b/pkg/providers/cohere/finish_reason.go index 6133ea39..139498e6 100644 --- a/pkg/providers/cohere/finish_reason.go +++ b/pkg/providers/cohere/finish_reason.go @@ -3,8 +3,9 @@ package cohere import ( "strings" - "glide/pkg/api/schemas" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/api/schemas" "go.uber.org/zap" ) @@ -35,18 +36,18 @@ func (m *FinishReasonMapper) Map(finishReason *string) *schemas.FinishReason { switch strings.ToLower(*finishReason) { case CompleteReason: - reason = &schemas.Complete + reason = &schemas.ReasonComplete case MaxTokensReason: - reason = &schemas.MaxTokens + reason = &schemas.ReasonMaxTokens case FilteredReason: - reason = &schemas.ContentFiltered + reason = &schemas.ReasonContentFiltered default: m.tel.Logger.Warn( "Unknown finish reason, other is going to used", zap.String("unknown_reason", *finishReason), ) - reason = &schemas.OtherReason + reason = &schemas.ReasonOther } return reason diff --git a/pkg/providers/cohere/schemas.go b/pkg/providers/cohere/schemas.go index 8516b306..9dc9bb09 100644 --- a/pkg/providers/cohere/schemas.go +++ b/pkg/providers/cohere/schemas.go @@ -1,5 +1,7 @@ package cohere +import "github.com/EinStack/glide/pkg/api/schemas" + // Cohere Chat Response type ChatCompletion struct { Text string `json:"text"` @@ -85,30 +87,35 @@ type FinalResponse struct { Meta Meta `json:"meta"` } -type ChatMessage struct { - Role string `json:"role"` // CHATBOT, SYSTEM, USER - Content string `json:"content"` -} - // ChatRequest is a request to complete a chat completion // Ref: https://docs.cohere.com/reference/chat type ChatRequest struct { - Model string `json:"model"` - Message string `json:"message"` - ChatHistory []ChatMessage `json:"chat_history"` - Temperature float64 `json:"temperature,omitempty"` - Preamble string `json:"preamble,omitempty"` - PromptTruncation *string `json:"prompt_truncation,omitempty"` - Connectors []string `json:"connectors,omitempty"` - SearchQueriesOnly bool `json:"search_queries_only,omitempty"` - Stream bool `json:"stream,omitempty"` - Seed *int `json:"seed,omitempty"` - MaxTokens *int `json:"max_tokens,omitempty"` - K int `json:"k"` - P float32 `json:"p"` - FrequencyPenalty float32 `json:"frequency_penalty"` - PresencePenalty float32 `json:"presence_penalty"` - StopSequences []string `json:"stop_sequences"` + Model string `json:"model"` + Message string `json:"message"` + ChatHistory []schemas.ChatMessage `json:"chat_history"` + Temperature float64 `json:"temperature,omitempty"` + Preamble string `json:"preamble,omitempty"` + PromptTruncation *string `json:"prompt_truncation,omitempty"` + Connectors []string `json:"connectors,omitempty"` + SearchQueriesOnly bool `json:"search_queries_only,omitempty"` + Stream bool `json:"stream,omitempty"` + Seed *int `json:"seed,omitempty"` + MaxTokens *int `json:"max_tokens,omitempty"` + K int `json:"k"` + P float32 `json:"p"` + FrequencyPenalty float32 `json:"frequency_penalty"` + PresencePenalty float32 `json:"presence_penalty"` + StopSequences []string `json:"stop_sequences"` +} + +func (r *ChatRequest) ApplyParams(params *schemas.ChatParams) { + message := params.Messages[len(params.Messages)-1] + messageHistory := params.Messages[:len(params.Messages)-1] + + // TODO: Map chat message roles to Cohere roles: CHATBOT, SYSTEM, USER + + r.Message = message.Content + r.ChatHistory = messageHistory } type Connectors struct { diff --git a/pkg/providers/config.go b/pkg/providers/config.go index 58aebff7..206be273 100644 --- a/pkg/providers/config.go +++ b/pkg/providers/config.go @@ -4,20 +4,27 @@ import ( "errors" "fmt" - "glide/pkg/routers/latency" + "github.com/EinStack/glide/pkg/routers/latency" - "glide/pkg/providers/bedrock" - "glide/pkg/providers/clients" - "glide/pkg/providers/ollama" + "github.com/EinStack/glide/pkg/providers/ollama" - "glide/pkg/routers/health" + "github.com/EinStack/glide/pkg/providers/clients" - "glide/pkg/providers/anthropic" - "glide/pkg/providers/azureopenai" - "glide/pkg/providers/cohere" - "glide/pkg/providers/octoml" - "glide/pkg/providers/openai" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/providers/bedrock" + + "github.com/EinStack/glide/pkg/routers/health" + + "github.com/EinStack/glide/pkg/providers/openai" + + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/providers/octoml" + + "github.com/EinStack/glide/pkg/providers/cohere" + + "github.com/EinStack/glide/pkg/providers/azureopenai" + + "github.com/EinStack/glide/pkg/providers/anthropic" ) var ErrProviderNotFound = errors.New("provider not found") diff --git a/pkg/providers/lang.go b/pkg/providers/lang.go index 7ac96724..d2a6aa06 100644 --- a/pkg/providers/lang.go +++ b/pkg/providers/lang.go @@ -5,13 +5,15 @@ import ( "io" "time" - "glide/pkg/config/fields" + "github.com/EinStack/glide/pkg/config/fields" - "glide/pkg/routers/health" + "github.com/EinStack/glide/pkg/routers/health" - "glide/pkg/api/schemas" - "glide/pkg/providers/clients" - "glide/pkg/routers/latency" + "github.com/EinStack/glide/pkg/routers/latency" + + "github.com/EinStack/glide/pkg/providers/clients" + + "github.com/EinStack/glide/pkg/api/schemas" ) // LangProvider defines an interface a provider should fulfill to be able to serve language chat requests @@ -20,15 +22,16 @@ type LangProvider interface { SupportChatStream() bool - Chat(ctx context.Context, req *schemas.ChatRequest) (*schemas.ChatResponse, error) - ChatStream(ctx context.Context, req *schemas.ChatStreamRequest) (clients.ChatStream, error) + Chat(ctx context.Context, params *schemas.ChatParams) (*schemas.ChatResponse, error) + ChatStream(ctx context.Context, params *schemas.ChatParams) (clients.ChatStream, error) } type LangModel interface { Model Provider() string - Chat(ctx context.Context, req *schemas.ChatRequest) (*schemas.ChatResponse, error) - ChatStream(ctx context.Context, req *schemas.ChatStreamRequest) (<-chan *clients.ChatStreamResult, error) + ModelName() string + Chat(ctx context.Context, params *schemas.ChatParams) (*schemas.ChatResponse, error) + ChatStream(ctx context.Context, params *schemas.ChatParams) (<-chan *clients.ChatStreamResult, error) } // LanguageModel wraps provider client and expend it with health & latency tracking @@ -85,10 +88,10 @@ func (m LanguageModel) ChatStreamLatency() *latency.MovingAverage { return m.chatStreamLatency } -func (m *LanguageModel) Chat(ctx context.Context, request *schemas.ChatRequest) (*schemas.ChatResponse, error) { +func (m *LanguageModel) Chat(ctx context.Context, params *schemas.ChatParams) (*schemas.ChatResponse, error) { startedAt := time.Now() - resp, err := m.client.Chat(ctx, request) + resp, err := m.client.Chat(ctx, params) if err != nil { m.healthTracker.TrackErr(err) @@ -104,8 +107,8 @@ func (m *LanguageModel) Chat(ctx context.Context, request *schemas.ChatRequest) return resp, err } -func (m *LanguageModel) ChatStream(ctx context.Context, req *schemas.ChatStreamRequest) (<-chan *clients.ChatStreamResult, error) { - stream, err := m.client.ChatStream(ctx, req) +func (m *LanguageModel) ChatStream(ctx context.Context, params *schemas.ChatParams) (<-chan *clients.ChatStreamResult, error) { + stream, err := m.client.ChatStream(ctx, params) if err != nil { m.healthTracker.TrackErr(err) @@ -172,6 +175,10 @@ func (m *LanguageModel) Provider() string { return m.client.Provider() } +func (m *LanguageModel) ModelName() string { + return m.client.ModelName() +} + func ChatLatency(model Model) *latency.MovingAverage { return model.(LanguageModel).ChatLatency() } diff --git a/pkg/providers/octoml/chat.go b/pkg/providers/octoml/chat.go index 5a0aa2bc..92f20fbf 100644 --- a/pkg/providers/octoml/chat.go +++ b/pkg/providers/octoml/chat.go @@ -8,82 +8,61 @@ import ( "io" "net/http" - "glide/pkg/providers/openai" + "github.com/EinStack/glide/pkg/providers/openai" + + "github.com/EinStack/glide/pkg/api/schemas" - "glide/pkg/api/schemas" "go.uber.org/zap" ) -type ChatMessage struct { - Role string `json:"role"` - Content string `json:"content"` -} - // ChatRequest is an octoml-specific request schema type ChatRequest struct { - Model string `json:"model"` - Messages []ChatMessage `json:"messages"` - Temperature float64 `json:"temperature,omitempty"` - TopP float64 `json:"top_p,omitempty"` - MaxTokens int `json:"max_tokens,omitempty"` - StopWords []string `json:"stop,omitempty"` - Stream bool `json:"stream,omitempty"` - FrequencyPenalty int `json:"frequency_penalty,omitempty"` - PresencePenalty int `json:"presence_penalty,omitempty"` + Model string `json:"model"` + Messages []schemas.ChatMessage `json:"messages"` + Temperature float64 `json:"temperature,omitempty"` + TopP float64 `json:"top_p,omitempty"` + MaxTokens int `json:"max_tokens,omitempty"` + StopWords []string `json:"stop,omitempty"` + Stream bool `json:"stream,omitempty"` + FrequencyPenalty int `json:"frequency_penalty,omitempty"` + PresencePenalty int `json:"presence_penalty,omitempty"` +} + +func (r *ChatRequest) ApplyParams(params *schemas.ChatParams) { + // TODO(185): set other params + r.Messages = params.Messages } // NewChatRequestFromConfig fills the struct from the config. Not using reflection because of performance penalty it gives func NewChatRequestFromConfig(cfg *Config) *ChatRequest { return &ChatRequest{ - Model: cfg.Model, + Model: cfg.ModelName, Temperature: cfg.DefaultParams.Temperature, TopP: cfg.DefaultParams.TopP, MaxTokens: cfg.DefaultParams.MaxTokens, StopWords: cfg.DefaultParams.StopWords, - Stream: false, // unsupported right now FrequencyPenalty: cfg.DefaultParams.FrequencyPenalty, PresencePenalty: cfg.DefaultParams.PresencePenalty, } } -func NewChatMessagesFromUnifiedRequest(request *schemas.ChatRequest) []ChatMessage { - messages := make([]ChatMessage, 0, len(request.MessageHistory)+1) - - // Add items from messageHistory first and the new chat message last - for _, message := range request.MessageHistory { - messages = append(messages, ChatMessage{Role: message.Role, Content: message.Content}) - } - - messages = append(messages, ChatMessage{Role: request.Message.Role, Content: request.Message.Content}) - - return messages -} - // Chat sends a chat request to the specified octoml model. -func (c *Client) Chat(ctx context.Context, request *schemas.ChatRequest) (*schemas.ChatResponse, error) { +func (c *Client) Chat(ctx context.Context, params *schemas.ChatParams) (*schemas.ChatResponse, error) { // Create a new chat request - chatRequest := c.createChatRequestSchema(request) + // TODO: consider using objectpool to optimize memory allocation + chatReq := *c.chatRequestTemplate // hoping to get a copy of the template + chatReq.ApplyParams(params) - chatResponse, err := c.doChatRequest(ctx, chatRequest) + chatReq.Stream = false + + chatResponse, err := c.doChatRequest(ctx, &chatReq) if err != nil { return nil, err } - if len(chatResponse.ModelResponse.Message.Content) == 0 { - return nil, ErrEmptyResponse - } - return chatResponse, nil } -func (c *Client) createChatRequestSchema(request *schemas.ChatRequest) *ChatRequest { - // TODO: consider using objectpool to optimize memory allocation - chatRequest := c.chatRequestTemplate // hoping to get a copy of the template - chatRequest.Messages = NewChatMessagesFromUnifiedRequest(request) - - return chatRequest -} - func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*schemas.ChatResponse, error) { // Build request payload rawPayload, err := json.Marshal(payload) @@ -125,33 +104,39 @@ func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*sche } // Parse the response JSON - var openAICompletion openai.ChatCompletion // Octo uses the same response schema as OpenAI + var completion openai.ChatCompletion // Octo uses the same response schema as OpenAI - err = json.Unmarshal(bodyBytes, &openAICompletion) + err = json.Unmarshal(bodyBytes, &completion) if err != nil { c.telemetry.Logger.Error("failed to parse openai chat response", zap.Error(err)) return nil, err } + modelChoice := completion.Choices[0] + + if len(modelChoice.Message.Content) == 0 { + return nil, ErrEmptyResponse + } + // Map response to UnifiedChatResponse schema response := schemas.ChatResponse{ - ID: openAICompletion.ID, - Created: openAICompletion.Created, + ID: completion.ID, + Created: completion.Created, Provider: providerName, - ModelName: openAICompletion.ModelName, + ModelName: completion.ModelName, Cached: false, ModelResponse: schemas.ModelResponse{ - SystemID: map[string]string{ - "system_fingerprint": openAICompletion.SystemFingerprint, + Metadata: map[string]string{ + "system_fingerprint": completion.SystemFingerprint, }, Message: schemas.ChatMessage{ - Role: openAICompletion.Choices[0].Message.Role, - Content: openAICompletion.Choices[0].Message.Content, + Role: modelChoice.Message.Role, + Content: modelChoice.Message.Content, }, TokenUsage: schemas.TokenUsage{ - PromptTokens: openAICompletion.Usage.PromptTokens, - ResponseTokens: openAICompletion.Usage.CompletionTokens, - TotalTokens: openAICompletion.Usage.TotalTokens, + PromptTokens: completion.Usage.PromptTokens, + ResponseTokens: completion.Usage.CompletionTokens, + TotalTokens: completion.Usage.TotalTokens, }, }, } diff --git a/pkg/providers/octoml/chat_stream.go b/pkg/providers/octoml/chat_stream.go index 2885195b..d0e33420 100644 --- a/pkg/providers/octoml/chat_stream.go +++ b/pkg/providers/octoml/chat_stream.go @@ -3,14 +3,15 @@ package octoml import ( "context" - "glide/pkg/api/schemas" - "glide/pkg/providers/clients" + "github.com/EinStack/glide/pkg/providers/clients" + + "github.com/EinStack/glide/pkg/api/schemas" ) func (c *Client) SupportChatStream() bool { return false } -func (c *Client) ChatStream(_ context.Context, _ *schemas.ChatStreamRequest) (clients.ChatStream, error) { +func (c *Client) ChatStream(_ context.Context, _ *schemas.ChatParams) (clients.ChatStream, error) { return nil, clients.ErrChatStreamNotImplemented } diff --git a/pkg/providers/octoml/client.go b/pkg/providers/octoml/client.go index 66e71502..07f889bb 100644 --- a/pkg/providers/octoml/client.go +++ b/pkg/providers/octoml/client.go @@ -4,9 +4,11 @@ import ( "errors" "net/http" "net/url" + "time" - "glide/pkg/providers/clients" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/providers/clients" ) const ( @@ -43,11 +45,10 @@ func NewClient(providerConfig *Config, clientConfig *clients.ClientConfig, tel * chatRequestTemplate: NewChatRequestFromConfig(providerConfig), errMapper: NewErrorMapper(tel), httpClient: &http.Client{ - Timeout: *clientConfig.Timeout, - // TODO: use values from the config + Timeout: time.Duration(*clientConfig.Timeout), Transport: &http.Transport{ - MaxIdleConns: 100, - MaxIdleConnsPerHost: 2, + MaxIdleConns: *clientConfig.MaxIdleConns, + MaxIdleConnsPerHost: *clientConfig.MaxIdleConnsPerHost, }, }, telemetry: tel, @@ -59,3 +60,7 @@ func NewClient(providerConfig *Config, clientConfig *clients.ClientConfig, tel * func (c *Client) Provider() string { return providerName } + +func (c *Client) ModelName() string { + return c.config.ModelName +} diff --git a/pkg/providers/octoml/client_test.go b/pkg/providers/octoml/client_test.go index b6f41b95..f35de1f7 100644 --- a/pkg/providers/octoml/client_test.go +++ b/pkg/providers/octoml/client_test.go @@ -10,11 +10,11 @@ import ( "path/filepath" "testing" - "glide/pkg/api/schemas" + "github.com/EinStack/glide/pkg/api/schemas" - "glide/pkg/providers/clients" + "github.com/EinStack/glide/pkg/providers/clients" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" "github.com/stretchr/testify/require" ) @@ -55,15 +55,15 @@ func TestOctoMLClient_ChatRequest(t *testing.T) { client, err := NewClient(providerCfg, clientCfg, telemetry.NewTelemetryMock()) require.NoError(t, err) - request := schemas.ChatRequest{Message: schemas.ChatMessage{ + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ Role: "human", Content: "What's the biggest animal?", - }} + }}} - response, err := client.Chat(ctx, &request) + response, err := client.Chat(ctx, &chatParams) require.NoError(t, err) - require.Equal(t, providerCfg.Model, response.ModelName) + require.Equal(t, providerCfg.ModelName, response.ModelName) require.Equal(t, "cmpl-8ea213aece0747aca6d0608b02b57196", response.ID) } @@ -88,15 +88,13 @@ func TestOctoMLClient_Chat_Error(t *testing.T) { require.NoError(t, err) // Create a chat request - request := schemas.ChatRequest{ - Message: schemas.ChatMessage{ - Role: "human", - Content: "What's the biggest animal?", - }, - } + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ + Role: "human", + Content: "What's the biggest animal?", + }}} // Call the Chat function - _, err = client.Chat(ctx, &request) + _, err = client.Chat(ctx, &chatParams) // Check the error require.Error(t, err) @@ -122,9 +120,12 @@ func TestDoChatRequest_ErrorResponse(t *testing.T) { require.NoError(t, err) // Create a chat request payload - payload := schemas.NewChatFromStr("What's the dealio?") + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ + Role: "user", + Content: "What's the dealeo?", + }}} - _, err = client.Chat(ctx, payload) + _, err = client.Chat(ctx, &chatParams) require.Error(t, err) require.Contains(t, err.Error(), "provider is not available") diff --git a/pkg/providers/octoml/config.go b/pkg/providers/octoml/config.go index ed79fce5..2267e714 100644 --- a/pkg/providers/octoml/config.go +++ b/pkg/providers/octoml/config.go @@ -1,7 +1,7 @@ package octoml import ( - "glide/pkg/config/fields" + "github.com/EinStack/glide/pkg/config/fields" ) // Params defines OctoML-specific model params with the specific validation of values @@ -13,7 +13,6 @@ type Params struct { StopWords []string `yaml:"stop,omitempty" json:"stop"` FrequencyPenalty int `yaml:"frequency_penalty,omitempty" json:"frequency_penalty"` PresencePenalty int `yaml:"presence_penalty,omitempty" json:"presence_penalty"` - // Stream bool `json:"stream,omitempty"` // TODO: we are not supporting this at the moment } func DefaultParams() Params { @@ -34,11 +33,11 @@ func (p *Params) UnmarshalYAML(unmarshal func(interface{}) error) error { } type Config struct { - BaseURL string `yaml:"base_url" json:"baseUrl" validate:"required"` - ChatEndpoint string `yaml:"chat_endpoint" json:"chatEndpoint" validate:"required"` - Model string `yaml:"model" json:"model" validate:"required"` + BaseURL string `yaml:"base_url" json:"base_url" validate:"required"` + ChatEndpoint string `yaml:"chat_endpoint" json:"chat_endpoint" validate:"required"` + ModelName string `yaml:"model" json:"model" validate:"required"` APIKey fields.Secret `yaml:"api_key" json:"-" validate:"required"` - DefaultParams *Params `yaml:"default_params,omitempty" json:"defaultParams"` + DefaultParams *Params `yaml:"default_params,omitempty" json:"default_params"` } // DefaultConfig for OctoML models @@ -48,7 +47,7 @@ func DefaultConfig() *Config { return &Config{ BaseURL: "https://text.octoai.run/v1", ChatEndpoint: "/chat/completions", - Model: "mistral-7b-instruct-fp16", + ModelName: "mistral-7b-instruct-fp16", DefaultParams: &defaultParams, } } diff --git a/pkg/providers/octoml/errors.go b/pkg/providers/octoml/errors.go index 23657076..97f16840 100644 --- a/pkg/providers/octoml/errors.go +++ b/pkg/providers/octoml/errors.go @@ -6,8 +6,9 @@ import ( "net/http" "time" - "glide/pkg/providers/clients" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/providers/clients" "go.uber.org/zap" ) diff --git a/pkg/providers/ollama/chat.go b/pkg/providers/ollama/chat.go index dd4a22fc..b93f5b10 100644 --- a/pkg/providers/ollama/chat.go +++ b/pkg/providers/ollama/chat.go @@ -9,45 +9,46 @@ import ( "net/http" "time" - "glide/pkg/providers/clients" + "github.com/EinStack/glide/pkg/providers/clients" "github.com/google/uuid" - "glide/pkg/api/schemas" + "github.com/EinStack/glide/pkg/api/schemas" + "go.uber.org/zap" ) -type ChatMessage struct { - Role string `json:"role"` - Content string `json:"content"` -} - // ChatRequest is an ollama-specific request schema type ChatRequest struct { - Model string `json:"model"` - Messages []ChatMessage `json:"messages"` - Microstat int `json:"microstat,omitempty"` - MicrostatEta float64 `json:"microstat_eta,omitempty"` - MicrostatTau float64 `json:"microstat_tau,omitempty"` - NumCtx int `json:"num_ctx,omitempty"` - NumGqa int `json:"num_gqa,omitempty"` - NumGpu int `json:"num_gpu,omitempty"` - NumThread int `json:"num_thread,omitempty"` - RepeatLastN int `json:"repeat_last_n,omitempty"` - Temperature float64 `json:"temperature,omitempty"` - Seed int `json:"seed,omitempty"` - StopWords []string `json:"stop,omitempty"` - Tfsz float64 `json:"tfs_z,omitempty"` - NumPredict int `json:"num_predict,omitempty"` - TopK int `json:"top_k,omitempty"` - TopP float64 `json:"top_p,omitempty"` - Stream bool `json:"stream"` + Model string `json:"model"` + Messages []schemas.ChatMessage `json:"messages"` + Microstat int `json:"microstat,omitempty"` + MicrostatEta float64 `json:"microstat_eta,omitempty"` + MicrostatTau float64 `json:"microstat_tau,omitempty"` + NumCtx int `json:"num_ctx,omitempty"` + NumGqa int `json:"num_gqa,omitempty"` + NumGpu int `json:"num_gpu,omitempty"` + NumThread int `json:"num_thread,omitempty"` + RepeatLastN int `json:"repeat_last_n,omitempty"` + Temperature float64 `json:"temperature,omitempty"` + Seed int `json:"seed,omitempty"` + StopWords []string `json:"stop,omitempty"` + Tfsz float64 `json:"tfs_z,omitempty"` + NumPredict int `json:"num_predict,omitempty"` + TopK int `json:"top_k,omitempty"` + TopP float64 `json:"top_p,omitempty"` + Stream bool `json:"stream"` +} + +func (r *ChatRequest) ApplyParams(params *schemas.ChatParams) { + // TODO(185): set other params + r.Messages = params.Messages } // NewChatRequestFromConfig fills the struct from the config. Not using reflection because of performance penalty it gives func NewChatRequestFromConfig(cfg *Config) *ChatRequest { return &ChatRequest{ - Model: cfg.Model, + Model: cfg.ModelName, Temperature: cfg.DefaultParams.Temperature, Microstat: cfg.DefaultParams.Microstat, MicrostatEta: cfg.DefaultParams.MicrostatEta, @@ -63,49 +64,27 @@ func NewChatRequestFromConfig(cfg *Config) *ChatRequest { NumPredict: cfg.DefaultParams.NumPredict, TopP: cfg.DefaultParams.TopP, TopK: cfg.DefaultParams.TopK, - Stream: cfg.DefaultParams.Stream, - } -} - -func NewChatMessagesFromUnifiedRequest(request *schemas.ChatRequest) []ChatMessage { - messages := make([]ChatMessage, 0, len(request.MessageHistory)+1) - - // Add items from messageHistory first and the new chat message last - for _, message := range request.MessageHistory { - messages = append(messages, ChatMessage{Role: message.Role, Content: message.Content}) } - - messages = append(messages, ChatMessage{Role: request.Message.Role, Content: request.Message.Content}) - - return messages } // Chat sends a chat request to the specified ollama model. -func (c *Client) Chat(ctx context.Context, request *schemas.ChatRequest) (*schemas.ChatResponse, error) { +func (c *Client) Chat(ctx context.Context, params *schemas.ChatParams) (*schemas.ChatResponse, error) { // Create a new chat request - chatRequest := c.createChatRequestSchema(request) + // TODO: consider using objectpool to optimize memory allocation + chatReq := *c.chatRequestTemplate // hoping to get a copy of the template + chatReq.ApplyParams(params) - chatResponse, err := c.doChatRequest(ctx, chatRequest) + chatReq.Stream = false + + chatResponse, err := c.doChatRequest(ctx, &chatReq) if err != nil { return nil, fmt.Errorf("chat request failed: %w", err) } - if len(chatResponse.ModelResponse.Message.Content) == 0 { - return nil, ErrEmptyResponse - } - return chatResponse, nil } -func (c *Client) createChatRequestSchema(request *schemas.ChatRequest) *ChatRequest { - // TODO: consider using objectpool to optimize memory allocation - chatRequest := c.chatRequestTemplate // hoping to get a copy of the template - chatRequest.Messages = NewChatMessagesFromUnifiedRequest(request) - - return chatRequest -} - -func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*schemas.ChatResponse, error) { +func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*schemas.ChatResponse, error) { //nolint:cyclop // Build request payload rawPayload, err := json.Marshal(payload) if err != nil { @@ -167,6 +146,7 @@ func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*sche bodyBytes, err := io.ReadAll(resp.Body) if err != nil { c.telemetry.Logger.Error("failed to read ollama chat response", zap.Error(err)) + return nil, err } @@ -179,6 +159,10 @@ func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*sche return nil, err } + if len(ollamaCompletion.Message.Content) == 0 { + return nil, clients.ErrEmptyResponse + } + // Map response to UnifiedChatResponse schema response := schemas.ChatResponse{ ID: uuid.NewString(), @@ -187,9 +171,6 @@ func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*sche ModelName: ollamaCompletion.Model, Cached: false, ModelResponse: schemas.ModelResponse{ - SystemID: map[string]string{ - "system_fingerprint": "", - }, Message: schemas.ChatMessage{ Role: ollamaCompletion.Message.Role, Content: ollamaCompletion.Message.Content, diff --git a/pkg/providers/ollama/chat_stream.go b/pkg/providers/ollama/chat_stream.go index 2bf0b87f..31075ca1 100644 --- a/pkg/providers/ollama/chat_stream.go +++ b/pkg/providers/ollama/chat_stream.go @@ -3,14 +3,15 @@ package ollama import ( "context" - "glide/pkg/api/schemas" - "glide/pkg/providers/clients" + "github.com/EinStack/glide/pkg/providers/clients" + + "github.com/EinStack/glide/pkg/api/schemas" ) func (c *Client) SupportChatStream() bool { return false } -func (c *Client) ChatStream(_ context.Context, _ *schemas.ChatStreamRequest) (clients.ChatStream, error) { +func (c *Client) ChatStream(_ context.Context, _ *schemas.ChatParams) (clients.ChatStream, error) { return nil, clients.ErrChatStreamNotImplemented } diff --git a/pkg/providers/ollama/client.go b/pkg/providers/ollama/client.go index 00043025..5a61898e 100644 --- a/pkg/providers/ollama/client.go +++ b/pkg/providers/ollama/client.go @@ -1,23 +1,19 @@ package ollama import ( - "errors" "net/http" "net/url" + "time" - "glide/pkg/providers/clients" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/providers/clients" ) const ( providerName = "ollama" ) -// ErrEmptyResponse is returned when the OpenAI API returns an empty response. -var ( - ErrEmptyResponse = errors.New("empty response") -) - // Client is a client for accessing OpenAI API type Client struct { baseURL string @@ -41,11 +37,10 @@ func NewClient(providerConfig *Config, clientConfig *clients.ClientConfig, tel * config: providerConfig, chatRequestTemplate: NewChatRequestFromConfig(providerConfig), httpClient: &http.Client{ - Timeout: *clientConfig.Timeout, - // TODO: use values from the config + Timeout: time.Duration(*clientConfig.Timeout), Transport: &http.Transport{ - MaxIdleConns: 100, - MaxIdleConnsPerHost: 2, + MaxIdleConns: *clientConfig.MaxIdleConns, + MaxIdleConnsPerHost: *clientConfig.MaxIdleConnsPerHost, }, }, telemetry: tel, @@ -57,3 +52,7 @@ func NewClient(providerConfig *Config, clientConfig *clients.ClientConfig, tel * func (c *Client) Provider() string { return providerName } + +func (c *Client) ModelName() string { + return c.config.ModelName +} diff --git a/pkg/providers/ollama/client_test.go b/pkg/providers/ollama/client_test.go index 3a85d397..e6c584cf 100644 --- a/pkg/providers/ollama/client_test.go +++ b/pkg/providers/ollama/client_test.go @@ -10,11 +10,11 @@ import ( "path/filepath" "testing" - "glide/pkg/providers/clients" + "github.com/EinStack/glide/pkg/providers/clients" - "glide/pkg/api/schemas" + "github.com/EinStack/glide/pkg/api/schemas" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" "github.com/stretchr/testify/require" ) @@ -51,17 +51,17 @@ func TestOllamaClient_ChatRequest(t *testing.T) { clientCfg := clients.DefaultClientConfig() - providerCfg.Model = "llama2" + providerCfg.ModelName = "llama2" client, err := NewClient(providerCfg, clientCfg, telemetry.NewTelemetryMock()) require.NoError(t, err) - request := schemas.ChatRequest{Message: schemas.ChatMessage{ + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ Role: "user", Content: "What's the biggest animal?", - }} + }}} - _, err = client.Chat(ctx, &request) + _, err = client.Chat(ctx, &chatParams) // require.NoError(t, err) @@ -77,21 +77,19 @@ func TestOllamaClient_ChatRequest_Non200Response(t *testing.T) { defer mockServer.Close() - // Create a new client with the mock server URL - client := &Client{ - httpClient: http.DefaultClient, - chatURL: mockServer.URL, - config: DefaultConfig(), - telemetry: telemetry.NewTelemetryMock(), - } + providerCfg := DefaultConfig() + clientCfg := clients.DefaultClientConfig() + providerCfg.BaseURL = mockServer.URL + + client, err := NewClient(providerCfg, clientCfg, telemetry.NewTelemetryMock()) + require.NoError(t, err) - // Create a chat request payload - payload := &ChatRequest{ - Messages: []ChatMessage{{Role: "human", Content: "Hello"}}, - } + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ + Role: "user", + Content: "What's the capital of the United Kingdom?", + }}} - // Call the chatRequest function - _, err := client.doChatRequest(context.Background(), payload) + _, err = client.Chat(context.Background(), &chatParams) require.Error(t, err) require.Contains(t, err.Error(), "provider is not available") @@ -100,29 +98,38 @@ func TestOllamaClient_ChatRequest_Non200Response(t *testing.T) { func TestOllamaClient_ChatRequest_SuccessfulResponse(t *testing.T) { // Create a mock HTTP server that returns an OK status code and a sample response mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + chatResponse, err := os.ReadFile(filepath.Clean("./testdata/chat.success.json")) + if err != nil { + t.Errorf("error reading cohere chat mock response: %v", err) + } + w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(`{"response": "OK"}`)) + w.Header().Set("Content-Type", "application/json") + + _, err = w.Write(chatResponse) + if err != nil { + t.Errorf("error on sending chat response: %v", err) + } })) defer mockServer.Close() - // Create a new client with the mock server URL - client := &Client{ - httpClient: http.DefaultClient, - chatURL: mockServer.URL, - config: DefaultConfig(), - telemetry: telemetry.NewTelemetryMock(), - } + providerCfg := DefaultConfig() + clientCfg := clients.DefaultClientConfig() + providerCfg.BaseURL = mockServer.URL - // Create a chat request payload - payload := &ChatRequest{ - Messages: []ChatMessage{{Role: "human", Content: "Hello"}}, - } + client, err := NewClient(providerCfg, clientCfg, telemetry.NewTelemetryMock()) + require.NoError(t, err) + + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ + Role: "user", + Content: "What's the capital of the United Kingdom?", + }}} - // Call the chatRequest function - response, err := client.doChatRequest(context.Background(), payload) + response, err := client.Chat(context.Background(), &chatParams) require.NoError(t, err) require.NotNil(t, response) - require.Equal(t, "", response.ModelResponse.Message.Role) + require.Equal(t, "assistant", response.ModelResponse.Message.Role) + require.Equal(t, "London", response.ModelResponse.Message.Content) } diff --git a/pkg/providers/ollama/config.go b/pkg/providers/ollama/config.go index 7363db58..f37223ee 100644 --- a/pkg/providers/ollama/config.go +++ b/pkg/providers/ollama/config.go @@ -18,7 +18,6 @@ type Params struct { Tfsz float64 `yaml:"tfs_z,omitempty" json:"tfs_z"` NumPredict int `yaml:"num_predict,omitempty" json:"num_predict"` TopK int `yaml:"top_k,omitempty" json:"top_k"` - Stream bool `yaml:"stream,omitempty" json:"stream"` } func DefaultParams() Params { @@ -27,7 +26,6 @@ func DefaultParams() Params { NumCtx: 2048, TopP: 0.9, TopK: 40, - Stream: false, } } @@ -40,10 +38,10 @@ func (p *Params) UnmarshalYAML(unmarshal func(interface{}) error) error { } type Config struct { - BaseURL string `yaml:"baseUrl" json:"baseUrl" validate:"required"` - ChatEndpoint string `yaml:"chatEndpoint" json:"chatEndpoint" validate:"required"` - Model string `yaml:"model" json:"model" validate:"required"` - DefaultParams *Params `yaml:"defaultParams,omitempty" json:"defaultParams"` + BaseURL string `yaml:"base_url" json:"base_url" validate:"required"` + ChatEndpoint string `yaml:"chat_endpoint" json:"chat_endpoint" validate:"required"` + ModelName string `yaml:"model" json:"model" validate:"required"` + DefaultParams *Params `yaml:"default_params,omitempty" json:"default_params"` } // DefaultConfig for OpenAI models @@ -53,7 +51,7 @@ func DefaultConfig() *Config { return &Config{ BaseURL: "http://localhost:11434", ChatEndpoint: "/api/chat", - Model: "", + ModelName: "", DefaultParams: &defaultParams, } } diff --git a/pkg/providers/ollama/testdata/chat.success.json b/pkg/providers/ollama/testdata/chat.success.json index 0a674356..97b6d782 100644 --- a/pkg/providers/ollama/testdata/chat.success.json +++ b/pkg/providers/ollama/testdata/chat.success.json @@ -3,7 +3,7 @@ "created_at": "2023-12-12T14:13:43.416799Z", "message": { "role": "assistant", - "content": "Hello! How are you today?" + "content": "London" }, "done": true, "total_duration": 5191566416, @@ -12,4 +12,4 @@ "prompt_eval_duration": 383809000, "eval_count": 298, "eval_duration": 4799921000 -} \ No newline at end of file +} diff --git a/pkg/providers/openai/chat.go b/pkg/providers/openai/chat.go index b292c664..519d7d43 100644 --- a/pkg/providers/openai/chat.go +++ b/pkg/providers/openai/chat.go @@ -8,14 +8,16 @@ import ( "io" "net/http" - "glide/pkg/api/schemas" + "github.com/EinStack/glide/pkg/providers/clients" + + "github.com/EinStack/glide/pkg/api/schemas" "go.uber.org/zap" ) // NewChatRequestFromConfig fills the struct from the config. Not using reflection because of performance penalty it gives func NewChatRequestFromConfig(cfg *Config) *ChatRequest { return &ChatRequest{ - Model: cfg.Model, + Model: cfg.ModelName, Temperature: cfg.DefaultParams.Temperature, TopP: cfg.DefaultParams.TopP, MaxTokens: cfg.DefaultParams.MaxTokens, @@ -34,40 +36,22 @@ func NewChatRequestFromConfig(cfg *Config) *ChatRequest { } // Chat sends a chat request to the specified OpenAI model. -func (c *Client) Chat(ctx context.Context, request *schemas.ChatRequest) (*schemas.ChatResponse, error) { +func (c *Client) Chat(ctx context.Context, params *schemas.ChatParams) (*schemas.ChatResponse, error) { // Create a new chat request - chatRequest := c.createRequestSchema(request) - chatRequest.Stream = false + // TODO: consider using objectpool to optimize memory allocation + chatReq := *c.chatRequestTemplate // hoping to get a copy of the template + chatReq.ApplyParams(params) + + chatReq.Stream = false - chatResponse, err := c.doChatRequest(ctx, chatRequest) + chatResponse, err := c.doChatRequest(ctx, &chatReq) if err != nil { return nil, err } - if len(chatResponse.ModelResponse.Message.Content) == 0 { - return nil, ErrEmptyResponse - } - return chatResponse, nil } -// createRequestSchema creates a new ChatRequest object based on the given request. -func (c *Client) createRequestSchema(request *schemas.ChatRequest) *ChatRequest { - // TODO: consider using objectpool to optimize memory allocation - chatRequest := *c.chatRequestTemplate // hoping to get a copy of the template - - chatRequest.Messages = make([]ChatMessage, 0, len(request.MessageHistory)+1) - - // Add items from messageHistory first and the new chat message last - for _, message := range request.MessageHistory { - chatRequest.Messages = append(chatRequest.Messages, ChatMessage{Role: message.Role, Content: message.Content}) - } - - chatRequest.Messages = append(chatRequest.Messages, ChatMessage{Role: request.Message.Role, Content: request.Message.Content}) - - return &chatRequest -} - func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*schemas.ChatResponse, error) { // Build request payload rawPayload, err := json.Marshal(payload) @@ -116,6 +100,11 @@ func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*sche // Parse the response JSON var chatCompletion ChatCompletion + c.logger.Debug( + "Raw chat response", + zap.ByteString("resp", bodyBytes), + ) + err = json.Unmarshal(bodyBytes, &chatCompletion) if err != nil { c.logger.Error( @@ -127,6 +116,12 @@ func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*sche return nil, err } + modelChoice := chatCompletion.Choices[0] + + if len(modelChoice.Message.Content) == 0 { + return nil, clients.ErrEmptyResponse + } + // Map response to ChatResponse schema response := schemas.ChatResponse{ ID: chatCompletion.ID, @@ -135,12 +130,12 @@ func (c *Client) doChatRequest(ctx context.Context, payload *ChatRequest) (*sche ModelName: chatCompletion.ModelName, Cached: false, ModelResponse: schemas.ModelResponse{ - SystemID: map[string]string{ + Metadata: map[string]string{ "system_fingerprint": chatCompletion.SystemFingerprint, }, Message: schemas.ChatMessage{ - Role: chatCompletion.Choices[0].Message.Role, - Content: chatCompletion.Choices[0].Message.Content, + Role: modelChoice.Message.Role, + Content: modelChoice.Message.Content, }, TokenUsage: schemas.TokenUsage{ PromptTokens: chatCompletion.Usage.PromptTokens, diff --git a/pkg/providers/openai/chat_stream.go b/pkg/providers/openai/chat_stream.go index 0d33f52e..08ca2b21 100644 --- a/pkg/providers/openai/chat_stream.go +++ b/pkg/providers/openai/chat_stream.go @@ -8,11 +8,11 @@ import ( "io" "net/http" + "github.com/EinStack/glide/pkg/providers/clients" "github.com/r3labs/sse/v2" - "glide/pkg/providers/clients" "go.uber.org/zap" - "glide/pkg/api/schemas" + "github.com/EinStack/glide/pkg/api/schemas" ) var StreamDoneMarker = []byte("[DONE]") @@ -120,7 +120,7 @@ func (s *ChatStream) Recv() (*schemas.ChatStreamChunk, error) { "generated_at": completionChunk.Created, }, Message: schemas.ChatMessage{ - Role: responseChunk.Delta.Role, + Role: "assistant", // doesn't present in all chunks Content: responseChunk.Delta.Content, }, }, @@ -141,9 +141,9 @@ func (c *Client) SupportChatStream() bool { return true } -func (c *Client) ChatStream(ctx context.Context, req *schemas.ChatStreamRequest) (clients.ChatStream, error) { +func (c *Client) ChatStream(ctx context.Context, params *schemas.ChatParams) (clients.ChatStream, error) { // Create a new chat request - httpRequest, err := c.makeStreamReq(ctx, req) + httpRequest, err := c.makeStreamReq(ctx, params) if err != nil { return nil, err } @@ -157,28 +157,14 @@ func (c *Client) ChatStream(ctx context.Context, req *schemas.ChatStreamRequest) ), nil } -func (c *Client) createRequestFromStream(request *schemas.ChatStreamRequest) *ChatRequest { +func (c *Client) makeStreamReq(ctx context.Context, params *schemas.ChatParams) (*http.Request, error) { // TODO: consider using objectpool to optimize memory allocation - chatRequest := *c.chatRequestTemplate // hoping to get a copy of the template + chatReq := *c.chatRequestTemplate // hoping to get a copy of the template + chatReq.ApplyParams(params) - chatRequest.Messages = make([]ChatMessage, 0, len(request.MessageHistory)+1) + chatReq.Stream = true - // Add items from messageHistory first and the new chat message last - for _, message := range request.MessageHistory { - chatRequest.Messages = append(chatRequest.Messages, ChatMessage{Role: message.Role, Content: message.Content}) - } - - chatRequest.Messages = append(chatRequest.Messages, ChatMessage{Role: request.Message.Role, Content: request.Message.Content}) - - return &chatRequest -} - -func (c *Client) makeStreamReq(ctx context.Context, req *schemas.ChatStreamRequest) (*http.Request, error) { - chatRequest := c.createRequestFromStream(req) - - chatRequest.Stream = true - - rawPayload, err := json.Marshal(chatRequest) + rawPayload, err := json.Marshal(chatReq) if err != nil { return nil, fmt.Errorf("unable to marshal openAI chat stream request payload: %w", err) } @@ -198,7 +184,7 @@ func (c *Client) makeStreamReq(ctx context.Context, req *schemas.ChatStreamReque c.logger.Debug( "Stream chat request", zap.String("chatURL", c.chatURL), - zap.Any("payload", chatRequest), + zap.Any("payload", chatReq), ) return request, nil diff --git a/pkg/providers/openai/chat_stream_test.go b/pkg/providers/openai/chat_stream_test.go index ba1542da..1ab8483b 100644 --- a/pkg/providers/openai/chat_stream_test.go +++ b/pkg/providers/openai/chat_stream_test.go @@ -10,11 +10,13 @@ import ( "path/filepath" "testing" - "glide/pkg/api/schemas" + "github.com/EinStack/glide/pkg/api/schemas" + + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/providers/clients" "github.com/stretchr/testify/require" - "glide/pkg/providers/clients" - "glide/pkg/telemetry" ) func TestOpenAIClient_ChatStreamSupported(t *testing.T) { @@ -69,8 +71,12 @@ func TestOpenAIClient_ChatStreamRequest(t *testing.T) { client, err := NewClient(providerCfg, clientCfg, telemetry.NewTelemetryMock()) require.NoError(t, err) - req := schemas.NewChatStreamFromStr("What's the capital of the United Kingdom?") - stream, err := client.ChatStream(ctx, req) + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ + Role: "user", + Content: "What's the capital of the United Kingdom?", + }}} + + stream, err := client.ChatStream(ctx, &chatParams) require.NoError(t, err) err = stream.Open() @@ -133,8 +139,12 @@ func TestOpenAIClient_ChatStreamRequestInterrupted(t *testing.T) { client, err := NewClient(providerCfg, clientCfg, telemetry.NewTelemetryMock()) require.NoError(t, err) - req := schemas.NewChatStreamFromStr("What's the capital of the United Kingdom?") - stream, err := client.ChatStream(ctx, req) + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ + Role: "user", + Content: "What's the capital of the United Kingdom?", + }}} + + stream, err := client.ChatStream(ctx, &chatParams) require.NoError(t, err) err = stream.Open() diff --git a/pkg/providers/openai/chat_test.go b/pkg/providers/openai/chat_test.go index bde4486b..3109f150 100644 --- a/pkg/providers/openai/chat_test.go +++ b/pkg/providers/openai/chat_test.go @@ -10,10 +10,11 @@ import ( "path/filepath" "testing" - "glide/pkg/api/schemas" - "glide/pkg/providers/clients" + "github.com/EinStack/glide/pkg/providers/clients" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/api/schemas" + + "github.com/EinStack/glide/pkg/telemetry" "github.com/stretchr/testify/require" ) @@ -55,12 +56,12 @@ func TestOpenAIClient_ChatRequest(t *testing.T) { client, err := NewClient(providerCfg, clientCfg, telemetry.NewTelemetryMock()) require.NoError(t, err) - request := schemas.ChatRequest{Message: schemas.ChatMessage{ + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ Role: "user", - Content: "What's the biggest animal?", - }} + Content: "What's the capital of the United Kingdom?", + }}} - response, err := client.Chat(ctx, &request) + response, err := client.Chat(ctx, &chatParams) require.NoError(t, err) require.Equal(t, "chatcmpl-123", response.ID) @@ -84,12 +85,12 @@ func TestOpenAIClient_RateLimit(t *testing.T) { client, err := NewClient(providerCfg, clientCfg, telemetry.NewTelemetryMock()) require.NoError(t, err) - request := schemas.ChatRequest{Message: schemas.ChatMessage{ - Role: "user", + chatParams := schemas.ChatParams{Messages: []schemas.ChatMessage{{ + Role: "human", Content: "What's the biggest animal?", - }} + }}} - _, err = client.Chat(ctx, &request) + _, err = client.Chat(ctx, &chatParams) require.Error(t, err) require.IsType(t, &clients.RateLimitError{}, err) diff --git a/pkg/providers/openai/client.go b/pkg/providers/openai/client.go index 39af0d63..832ade57 100644 --- a/pkg/providers/openai/client.go +++ b/pkg/providers/openai/client.go @@ -1,25 +1,21 @@ package openai import ( - "errors" "net/http" "net/url" + "time" "go.uber.org/zap" - "glide/pkg/providers/clients" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/providers/clients" ) const ( providerName = "openai" ) -// ErrEmptyResponse is returned when the OpenAI API returns an empty response. -var ( - ErrEmptyResponse = errors.New("empty response") -) - // Client is a client for accessing OpenAI API type Client struct { baseURL string @@ -52,11 +48,10 @@ func NewClient(providerConfig *Config, clientConfig *clients.ClientConfig, tel * finishReasonMapper: NewFinishReasonMapper(tel), errMapper: NewErrorMapper(tel), httpClient: &http.Client{ - Timeout: *clientConfig.Timeout, - // TODO: use values from the config + Timeout: time.Duration(*clientConfig.Timeout), Transport: &http.Transport{ - MaxIdleConns: 100, - MaxIdleConnsPerHost: 2, + MaxIdleConns: *clientConfig.MaxIdleConns, + MaxIdleConnsPerHost: *clientConfig.MaxIdleConnsPerHost, }, }, tel: tel, @@ -69,3 +64,7 @@ func NewClient(providerConfig *Config, clientConfig *clients.ClientConfig, tel * func (c *Client) Provider() string { return providerName } + +func (c *Client) ModelName() string { + return c.config.ModelName +} diff --git a/pkg/providers/openai/config.go b/pkg/providers/openai/config.go index 49781d60..8342db41 100644 --- a/pkg/providers/openai/config.go +++ b/pkg/providers/openai/config.go @@ -1,7 +1,7 @@ package openai import ( - "glide/pkg/config/fields" + "github.com/EinStack/glide/pkg/config/fields" ) // Params defines OpenAI-specific model params with the specific validation of values @@ -42,11 +42,11 @@ func (p *Params) UnmarshalYAML(unmarshal func(interface{}) error) error { } type Config struct { - BaseURL string `yaml:"baseUrl" json:"baseUrl" validate:"required"` - ChatEndpoint string `yaml:"chatEndpoint" json:"chatEndpoint" validate:"required"` - Model string `yaml:"model" json:"model" validate:"required"` + BaseURL string `yaml:"base_url" json:"base_url" validate:"required"` + ChatEndpoint string `yaml:"chat_endpoint" json:"chat_endpoint" validate:"required"` + ModelName string `yaml:"model" json:"model" validate:"required"` APIKey fields.Secret `yaml:"api_key" json:"-" validate:"required"` - DefaultParams *Params `yaml:"defaultParams,omitempty" json:"defaultParams"` + DefaultParams *Params `yaml:"default_params,omitempty" json:"default_params"` } // DefaultConfig for OpenAI models @@ -56,7 +56,7 @@ func DefaultConfig() *Config { return &Config{ BaseURL: "https://api.openai.com/v1", ChatEndpoint: "/chat/completions", - Model: "gpt-3.5-turbo", + ModelName: "gpt-4o", DefaultParams: &defaultParams, } } diff --git a/pkg/providers/openai/errors.go b/pkg/providers/openai/errors.go index 94ef5418..14978f8c 100644 --- a/pkg/providers/openai/errors.go +++ b/pkg/providers/openai/errors.go @@ -6,8 +6,9 @@ import ( "net/http" "time" - "glide/pkg/providers/clients" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/providers/clients" "go.uber.org/zap" ) diff --git a/pkg/providers/openai/finish_reasons.go b/pkg/providers/openai/finish_reasons.go index 502d8725..28b5f675 100644 --- a/pkg/providers/openai/finish_reasons.go +++ b/pkg/providers/openai/finish_reasons.go @@ -1,8 +1,9 @@ package openai import ( - "glide/pkg/api/schemas" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/api/schemas" "go.uber.org/zap" ) @@ -33,18 +34,18 @@ func (m *FinishReasonMapper) Map(finishReason string) *schemas.FinishReason { switch finishReason { case CompleteReason: - reason = &schemas.Complete + reason = &schemas.ReasonComplete case MaxTokensReason: - reason = &schemas.MaxTokens + reason = &schemas.ReasonMaxTokens case FilteredReason: - reason = &schemas.ContentFiltered + reason = &schemas.ReasonContentFiltered default: m.tel.Logger.Warn( "Unknown finish reason, other is going to used", zap.String("unknown_reason", finishReason), ) - reason = &schemas.OtherReason + reason = &schemas.ReasonOther } return reason diff --git a/pkg/providers/openai/schemas.go b/pkg/providers/openai/schemas.go index 022d510e..bde0ba81 100644 --- a/pkg/providers/openai/schemas.go +++ b/pkg/providers/openai/schemas.go @@ -1,30 +1,30 @@ package openai -// OpenAI Chat Response (also used by Azure OpenAI and OctoML) - -type ChatMessage struct { - Role string `json:"role"` - Content string `json:"content"` -} +import "github.com/EinStack/glide/pkg/api/schemas" // ChatRequest is an OpenAI-specific request schema type ChatRequest struct { - Model string `json:"model"` - Messages []ChatMessage `json:"messages"` - Temperature float64 `json:"temperature,omitempty"` - TopP float64 `json:"top_p,omitempty"` - MaxTokens int `json:"max_tokens,omitempty"` - N int `json:"n,omitempty"` - StopWords []string `json:"stop,omitempty"` - Stream bool `json:"stream,omitempty"` - FrequencyPenalty int `json:"frequency_penalty,omitempty"` - PresencePenalty int `json:"presence_penalty,omitempty"` - LogitBias *map[int]float64 `json:"logit_bias,omitempty"` - User *string `json:"user,omitempty"` - Seed *int `json:"seed,omitempty"` - Tools []string `json:"tools,omitempty"` - ToolChoice interface{} `json:"tool_choice,omitempty"` - ResponseFormat interface{} `json:"response_format,omitempty"` + Model string `json:"model"` + Messages []schemas.ChatMessage `json:"messages"` + Temperature float64 `json:"temperature,omitempty"` + TopP float64 `json:"top_p,omitempty"` + MaxTokens int `json:"max_tokens,omitempty"` + N int `json:"n,omitempty"` + StopWords []string `json:"stop,omitempty"` + Stream bool `json:"stream,omitempty"` + FrequencyPenalty int `json:"frequency_penalty,omitempty"` + PresencePenalty int `json:"presence_penalty,omitempty"` + LogitBias *map[int]float64 `json:"logit_bias,omitempty"` + User *string `json:"user,omitempty"` + Seed *int `json:"seed,omitempty"` + Tools []string `json:"tools,omitempty"` + ToolChoice interface{} `json:"tool_choice,omitempty"` + ResponseFormat interface{} `json:"response_format,omitempty"` +} + +func (r *ChatRequest) ApplyParams(params *schemas.ChatParams) { + // TODO(185): set other params + r.Messages = params.Messages } // ChatCompletion @@ -40,10 +40,10 @@ type ChatCompletion struct { } type Choice struct { - Index int `json:"index"` - Message ChatMessage `json:"message"` - Logprobs interface{} `json:"logprobs"` - FinishReason string `json:"finish_reason"` + Index int `json:"index"` + Message schemas.ChatMessage `json:"message"` + Logprobs interface{} `json:"logprobs"` + FinishReason string `json:"finish_reason"` } type Usage struct { @@ -64,8 +64,8 @@ type ChatCompletionChunk struct { } type StreamChoice struct { - Index int `json:"index"` - Delta ChatMessage `json:"delta"` - Logprobs interface{} `json:"logprobs"` - FinishReason string `json:"finish_reason"` + Index int `json:"index"` + Delta schemas.ChatMessage `json:"delta"` + Logprobs interface{} `json:"logprobs"` + FinishReason string `json:"finish_reason"` } diff --git a/pkg/providers/provider.go b/pkg/providers/provider.go index 9d7bf9c7..91aded44 100644 --- a/pkg/providers/provider.go +++ b/pkg/providers/provider.go @@ -1,12 +1,13 @@ package providers import ( - "glide/pkg/config/fields" + "github.com/EinStack/glide/pkg/config/fields" ) // ModelProvider exposes provider context type ModelProvider interface { Provider() string + ModelName() string } // Model represent a configured external modality-agnostic model with its routing properties and status diff --git a/pkg/providers/testing/lang.go b/pkg/providers/testing/lang.go index 00389dac..0f7f1f4e 100644 --- a/pkg/providers/testing/lang.go +++ b/pkg/providers/testing/lang.go @@ -4,21 +4,22 @@ import ( "context" "io" - "glide/pkg/api/schemas" - "glide/pkg/providers/clients" + "github.com/EinStack/glide/pkg/providers/clients" + + "github.com/EinStack/glide/pkg/api/schemas" ) // RespMock mocks a chat response or a streaming chat chunk type RespMock struct { Msg string - Err *error + Err error } func (m *RespMock) Resp() *schemas.ChatResponse { return &schemas.ChatResponse{ ID: "rsp0001", ModelResponse: schemas.ModelResponse{ - SystemID: map[string]string{ + Metadata: map[string]string{ "ID": "0001", }, Message: schemas.ChatMessage{ @@ -80,7 +81,7 @@ func (m *RespStreamMock) Recv() (*schemas.ChatStreamChunk, error) { m.idx++ if chunk.Err != nil { - return nil, *chunk.Err + return nil, chunk.Err } return chunk.RespChunk(), nil @@ -96,19 +97,22 @@ type ProviderMock struct { chatResps *[]RespMock chatStreams *[]RespStreamMock supportStreaming bool + modelName *string } -func NewProviderMock(responses []RespMock) *ProviderMock { +func NewProviderMock(modelName *string, responses []RespMock) *ProviderMock { return &ProviderMock{ idx: 0, chatResps: &responses, supportStreaming: false, + modelName: modelName, } } -func NewStreamProviderMock(chatStreams []RespStreamMock) *ProviderMock { +func NewStreamProviderMock(modelName *string, chatStreams []RespStreamMock) *ProviderMock { return &ProviderMock{ idx: 0, + modelName: modelName, chatStreams: &chatStreams, supportStreaming: true, } @@ -118,7 +122,7 @@ func (c *ProviderMock) SupportChatStream() bool { return c.supportStreaming } -func (c *ProviderMock) Chat(_ context.Context, _ *schemas.ChatRequest) (*schemas.ChatResponse, error) { +func (c *ProviderMock) Chat(_ context.Context, _ *schemas.ChatParams) (*schemas.ChatResponse, error) { if c.chatResps == nil { return nil, clients.ErrProviderUnavailable } @@ -129,13 +133,13 @@ func (c *ProviderMock) Chat(_ context.Context, _ *schemas.ChatRequest) (*schemas c.idx++ if response.Err != nil { - return nil, *response.Err + return nil, response.Err } return response.Resp(), nil } -func (c *ProviderMock) ChatStream(_ context.Context, _ *schemas.ChatStreamRequest) (clients.ChatStream, error) { +func (c *ProviderMock) ChatStream(_ context.Context, _ *schemas.ChatParams) (clients.ChatStream, error) { if c.chatStreams == nil || c.idx >= len(*c.chatStreams) { return nil, clients.ErrProviderUnavailable } @@ -151,3 +155,11 @@ func (c *ProviderMock) ChatStream(_ context.Context, _ *schemas.ChatStreamReques func (c *ProviderMock) Provider() string { return "provider_mock" } + +func (c *ProviderMock) ModelName() string { + if c.modelName == nil { + return "model_mock" + } + + return *c.modelName +} diff --git a/pkg/providers/testing/models.go b/pkg/providers/testing/models.go index 712fcaf0..d4ac3840 100644 --- a/pkg/providers/testing/models.go +++ b/pkg/providers/testing/models.go @@ -3,10 +3,11 @@ package testing import ( "time" - "glide/pkg/config/fields" + "github.com/EinStack/glide/pkg/config/fields" - "glide/pkg/providers" - "glide/pkg/routers/latency" + "github.com/EinStack/glide/pkg/routers/latency" + + "github.com/EinStack/glide/pkg/providers" ) // LangModelMock diff --git a/pkg/routers/config.go b/pkg/routers/config.go index 19633688..c7651f6d 100644 --- a/pkg/routers/config.go +++ b/pkg/routers/config.go @@ -2,11 +2,15 @@ package routers import ( "fmt" + "time" - "glide/pkg/providers" - "glide/pkg/routers/retry" - "glide/pkg/routers/routing" - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/routers/routing" + + "github.com/EinStack/glide/pkg/routers/retry" + + "github.com/EinStack/glide/pkg/providers" "go.uber.org/multierr" "go.uber.org/zap" ) @@ -83,7 +87,7 @@ func (c *LangRouterConfig) BuildModels(tel *telemetry.Telemetry) ([]*providers.L if !modelConfig.Enabled { tel.L().Info( - "Model is disabled, skipping", + "ModelName is disabled, skipping", zap.String("router", c.ID), zap.String("model", modelConfig.ID), ) @@ -161,12 +165,13 @@ func (c *LangRouterConfig) BuildModels(tel *telemetry.Telemetry) ([]*providers.L func (c *LangRouterConfig) BuildRetry() *retry.ExpRetry { retryConfig := c.Retry + maxDelay := time.Duration(*retryConfig.MaxDelay) return retry.NewExpRetry( retryConfig.MaxRetries, retryConfig.BaseMultiplier, - retryConfig.MinDelay, - retryConfig.MaxDelay, + time.Duration(retryConfig.MinDelay), + &maxDelay, ) } diff --git a/pkg/routers/config_test.go b/pkg/routers/config_test.go index 28fb81fe..d740df2c 100644 --- a/pkg/routers/config_test.go +++ b/pkg/routers/config_test.go @@ -3,17 +3,25 @@ package routers import ( "testing" - "glide/pkg/providers/cohere" + "github.com/EinStack/glide/pkg/providers/cohere" + + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/routers/routing" + + "github.com/EinStack/glide/pkg/routers/retry" + + "github.com/EinStack/glide/pkg/routers/latency" + + "github.com/EinStack/glide/pkg/routers/health" + + "github.com/EinStack/glide/pkg/providers/openai" + + "github.com/EinStack/glide/pkg/providers/clients" + + "github.com/EinStack/glide/pkg/providers" "github.com/stretchr/testify/require" - "glide/pkg/providers" - "glide/pkg/providers/clients" - "glide/pkg/providers/openai" - "glide/pkg/routers/health" - "glide/pkg/routers/latency" - "glide/pkg/routers/retry" - "glide/pkg/routers/routing" - "glide/pkg/telemetry" ) func TestRouterConfig_BuildModels(t *testing.T) { diff --git a/pkg/routers/health/tracker.go b/pkg/routers/health/tracker.go index f49e310b..8cba6e65 100644 --- a/pkg/routers/health/tracker.go +++ b/pkg/routers/health/tracker.go @@ -3,7 +3,7 @@ package health import ( "errors" - "glide/pkg/providers/clients" + "github.com/EinStack/glide/pkg/providers/clients" ) // Tracker tracks errors and general health of model provider diff --git a/pkg/routers/health/tracker_test.go b/pkg/routers/health/tracker_test.go index 94733ce0..8927a041 100644 --- a/pkg/routers/health/tracker_test.go +++ b/pkg/routers/health/tracker_test.go @@ -4,8 +4,8 @@ import ( "testing" "time" + "github.com/EinStack/glide/pkg/providers/clients" "github.com/stretchr/testify/require" - "glide/pkg/providers/clients" ) func TestHealthTracker_HealthyByDefault(t *testing.T) { diff --git a/pkg/routers/latency/config.go b/pkg/routers/latency/config.go index c78cc7aa..07884606 100644 --- a/pkg/routers/latency/config.go +++ b/pkg/routers/latency/config.go @@ -3,7 +3,7 @@ package latency import ( "time" - "glide/pkg/config/fields" + "github.com/EinStack/glide/pkg/config/fields" ) // Config defines setting for moving average latency calculations diff --git a/pkg/routers/manager.go b/pkg/routers/manager.go index 8dcecd60..123ea09e 100644 --- a/pkg/routers/manager.go +++ b/pkg/routers/manager.go @@ -1,13 +1,10 @@ package routers import ( - "errors" - - "glide/pkg/telemetry" + "github.com/EinStack/glide/pkg/api/schemas" + "github.com/EinStack/glide/pkg/telemetry" ) -var ErrRouterNotFound = errors.New("no router found with given ID") - type RouterManager struct { Config *Config tel *telemetry.Telemetry @@ -48,5 +45,5 @@ func (r *RouterManager) GetLangRouter(routerID string) (*LangRouter, error) { return router, nil } - return nil, ErrRouterNotFound + return nil, &schemas.ErrRouterNotFound } diff --git a/pkg/routers/retry/config.go b/pkg/routers/retry/config.go index 6c3199a1..c2f21dcc 100644 --- a/pkg/routers/retry/config.go +++ b/pkg/routers/retry/config.go @@ -1,21 +1,25 @@ package retry -import "time" +import ( + "time" + + "github.com/EinStack/glide/pkg/config/fields" +) type ExpRetryConfig struct { - MaxRetries int `yaml:"max_retries,omitempty" json:"max_retries"` - BaseMultiplier int `yaml:"base_multiplier,omitempty" json:"base_multiplier"` - MinDelay time.Duration `yaml:"min_delay,omitempty" json:"min_delay" swaggertype:"primitive,integer"` - MaxDelay *time.Duration `yaml:"max_delay,omitempty" json:"max_delay" swaggertype:"primitive,integer"` + MaxRetries int `yaml:"max_retries,omitempty" json:"max_retries"` + BaseMultiplier int `yaml:"base_multiplier,omitempty" json:"base_multiplier"` + MinDelay fields.Duration `yaml:"min_delay,omitempty" json:"min_delay" swaggertype:"primitive,string"` + MaxDelay *fields.Duration `yaml:"max_delay,omitempty" json:"max_delay" swaggertype:"primitive,string"` } func DefaultExpRetryConfig() *ExpRetryConfig { - maxDelay := 5 * time.Second + maxDelay := fields.Duration(5 * time.Second) return &ExpRetryConfig{ MaxRetries: 3, BaseMultiplier: 2, - MinDelay: 2 * time.Second, + MinDelay: fields.Duration(2 * time.Second), MaxDelay: &maxDelay, } } diff --git a/pkg/routers/retry/config_test.go b/pkg/routers/retry/config_test.go index 7fe409a3..5ed36c3b 100644 --- a/pkg/routers/retry/config_test.go +++ b/pkg/routers/retry/config_test.go @@ -1,6 +1,7 @@ package retry import ( + "encoding/json" "testing" "github.com/stretchr/testify/require" @@ -11,3 +12,18 @@ func TestRetryConfig_DefaultConfig(t *testing.T) { require.NotNil(t, config) } + +func TestRetryConfig_JSONMarshal(t *testing.T) { + defaultConfig := DefaultExpRetryConfig() + + expectedJSON := `{ + "max_retries": 3, + "base_multiplier": 2, + "min_delay": "2s", + "max_delay": "5s" + }` + + marshaledJSON, err := json.MarshalIndent(defaultConfig, "", "\t") + require.NoError(t, err) + require.JSONEq(t, expectedJSON, string(marshaledJSON)) +} diff --git a/pkg/routers/router.go b/pkg/routers/router.go index fa9b9ef0..4a7d0d0f 100644 --- a/pkg/routers/router.go +++ b/pkg/routers/router.go @@ -4,21 +4,20 @@ import ( "context" "errors" - "glide/pkg/routers/retry" + "github.com/EinStack/glide/pkg/routers/retry" "go.uber.org/zap" - "glide/pkg/providers" + "github.com/EinStack/glide/pkg/providers" - "glide/pkg/api/schemas" - "glide/pkg/routers/routing" - "glide/pkg/telemetry" -) + "github.com/EinStack/glide/pkg/telemetry" + + "github.com/EinStack/glide/pkg/routers/routing" -var ( - ErrNoModels = errors.New("no models configured for router") - ErrNoModelAvailable = errors.New("could not handle request because all providers are not available") + "github.com/EinStack/glide/pkg/api/schemas" ) +var ErrNoModels = errors.New("no models configured for router") + type RouterID = string type LangRouter struct { @@ -83,15 +82,9 @@ func (r *LangRouter) Chat(ctx context.Context, req *schemas.ChatRequest) (*schem langModel := model.(providers.LangModel) - // Check if there is an override in the request - if req.Override != nil { - // Override the message if the language model ID matches the override model ID - if langModel.ID() == req.Override.Model { - req.Message = req.Override.Message - } - } + chatParams := req.Params(langModel.ID(), langModel.ModelName()) - resp, err := langModel.Chat(ctx, req) + resp, err := langModel.Chat(ctx, chatParams) if err != nil { r.logger.Warn( "Lang model failed processing chat request", @@ -122,7 +115,7 @@ func (r *LangRouter) Chat(ctx context.Context, req *schemas.ChatRequest) (*schem // if we reach this part, then we are in trouble r.logger.Error("No model was available to handle chat request") - return nil, ErrNoModelAvailable + return nil, &schemas.ErrNoModelAvailable } func (r *LangRouter) ChatStream( @@ -137,7 +130,7 @@ func (r *LangRouter) ChatStream( schemas.NoModelConfigured, ErrNoModels.Error(), req.Metadata, - &schemas.ErrorReason, + &schemas.ReasonError, ) return @@ -158,7 +151,9 @@ func (r *LangRouter) ChatStream( } langModel := model.(providers.LangModel) - modelRespC, err := langModel.ChatStream(ctx, req) + chatParams := req.Params(langModel.ID(), langModel.ModelName()) + + modelRespC, err := langModel.ChatStream(ctx, chatParams) if err != nil { r.logger.Error( "Lang model failed to create streaming chat request", @@ -237,9 +232,9 @@ func (r *LangRouter) ChatStream( respC <- schemas.NewChatStreamError( req.ID, r.routerID, - schemas.AllModelsUnavailable, - ErrNoModelAvailable.Error(), + schemas.ErrNoModelAvailable.Name, + schemas.ErrNoModelAvailable.Message, req.Metadata, - &schemas.ErrorReason, + &schemas.ReasonError, ) } diff --git a/pkg/routers/router_test.go b/pkg/routers/router_test.go index d5fa8640..f56216e3 100644 --- a/pkg/routers/router_test.go +++ b/pkg/routers/router_test.go @@ -5,18 +5,16 @@ import ( "testing" "time" - "glide/pkg/routers/latency" - - "glide/pkg/providers/clients" - + "github.com/EinStack/glide/pkg/api/schemas" + "github.com/EinStack/glide/pkg/providers" + "github.com/EinStack/glide/pkg/providers/clients" + ptesting "github.com/EinStack/glide/pkg/providers/testing" + "github.com/EinStack/glide/pkg/routers/health" + "github.com/EinStack/glide/pkg/routers/latency" + "github.com/EinStack/glide/pkg/routers/retry" + "github.com/EinStack/glide/pkg/routers/routing" + "github.com/EinStack/glide/pkg/telemetry" "github.com/stretchr/testify/require" - "glide/pkg/api/schemas" - "glide/pkg/providers" - ptesting "glide/pkg/providers/testing" - "glide/pkg/routers/health" - "glide/pkg/routers/retry" - "glide/pkg/routers/routing" - "glide/pkg/telemetry" ) func TestLangRouter_Chat_PickFistHealthy(t *testing.T) { @@ -26,14 +24,14 @@ func TestLangRouter_Chat_PickFistHealthy(t *testing.T) { langModels := []*providers.LanguageModel{ providers.NewLangModel( "first", - ptesting.NewProviderMock([]ptesting.RespMock{{Msg: "1"}, {Msg: "2"}}), + ptesting.NewProviderMock(nil, []ptesting.RespMock{{Msg: "1"}, {Msg: "2"}}), budget, *latConfig, 1, ), providers.NewLangModel( "second", - ptesting.NewProviderMock([]ptesting.RespMock{{Msg: "1"}}), + ptesting.NewProviderMock(nil, []ptesting.RespMock{{Msg: "1"}}), budget, *latConfig, 1, @@ -73,21 +71,21 @@ func TestLangRouter_Chat_PickThirdHealthy(t *testing.T) { langModels := []*providers.LanguageModel{ providers.NewLangModel( "first", - ptesting.NewProviderMock([]ptesting.RespMock{{Err: &ErrNoModelAvailable}, {Msg: "3"}}), + ptesting.NewProviderMock(nil, []ptesting.RespMock{{Err: &schemas.ErrNoModelAvailable}, {Msg: "3"}}), budget, *latConfig, 1, ), providers.NewLangModel( "second", - ptesting.NewProviderMock([]ptesting.RespMock{{Err: &ErrNoModelAvailable}, {Msg: "4"}}), + ptesting.NewProviderMock(nil, []ptesting.RespMock{{Err: &schemas.ErrNoModelAvailable}, {Msg: "4"}}), budget, *latConfig, 1, ), providers.NewLangModel( "third", - ptesting.NewProviderMock([]ptesting.RespMock{{Msg: "1"}, {Msg: "2"}}), + ptesting.NewProviderMock(nil, []ptesting.RespMock{{Msg: "1"}, {Msg: "2"}}), budget, *latConfig, 1, @@ -131,14 +129,14 @@ func TestLangRouter_Chat_SuccessOnRetry(t *testing.T) { langModels := []*providers.LanguageModel{ providers.NewLangModel( "first", - ptesting.NewProviderMock([]ptesting.RespMock{{Err: &ErrNoModelAvailable}, {Msg: "2"}}), + ptesting.NewProviderMock(nil, []ptesting.RespMock{{Err: &schemas.ErrNoModelAvailable}, {Msg: "2"}}), budget, *latConfig, 1, ), providers.NewLangModel( "second", - ptesting.NewProviderMock([]ptesting.RespMock{{Err: &ErrNoModelAvailable}, {Msg: "1"}}), + ptesting.NewProviderMock(nil, []ptesting.RespMock{{Err: &schemas.ErrNoModelAvailable}, {Msg: "1"}}), budget, *latConfig, 1, @@ -175,14 +173,14 @@ func TestLangRouter_Chat_UnhealthyModelInThePool(t *testing.T) { langModels := []*providers.LanguageModel{ providers.NewLangModel( "first", - ptesting.NewProviderMock([]ptesting.RespMock{{Err: &clients.ErrProviderUnavailable}, {Msg: "3"}}), + ptesting.NewProviderMock(nil, []ptesting.RespMock{{Err: clients.ErrProviderUnavailable}, {Msg: "3"}}), budget, *latConfig, 1, ), providers.NewLangModel( "second", - ptesting.NewProviderMock([]ptesting.RespMock{{Msg: "1"}, {Msg: "2"}}), + ptesting.NewProviderMock(nil, []ptesting.RespMock{{Msg: "1"}, {Msg: "2"}}), budget, *latConfig, 1, @@ -221,14 +219,14 @@ func TestLangRouter_Chat_AllModelsUnavailable(t *testing.T) { langModels := []*providers.LanguageModel{ providers.NewLangModel( "first", - ptesting.NewProviderMock([]ptesting.RespMock{{Err: &ErrNoModelAvailable}, {Err: &ErrNoModelAvailable}}), + ptesting.NewProviderMock(nil, []ptesting.RespMock{{Err: &schemas.ErrNoModelAvailable}, {Err: &schemas.ErrNoModelAvailable}}), budget, *latConfig, 1, ), providers.NewLangModel( "second", - ptesting.NewProviderMock([]ptesting.RespMock{{Err: &ErrNoModelAvailable}, {Err: &ErrNoModelAvailable}}), + ptesting.NewProviderMock(nil, []ptesting.RespMock{{Err: &schemas.ErrNoModelAvailable}, {Err: &schemas.ErrNoModelAvailable}}), budget, *latConfig, 1, @@ -264,7 +262,7 @@ func TestLangRouter_ChatStream(t *testing.T) { langModels := []*providers.LanguageModel{ providers.NewLangModel( "first", - ptesting.NewStreamProviderMock([]ptesting.RespStreamMock{ + ptesting.NewStreamProviderMock(nil, []ptesting.RespStreamMock{ ptesting.NewRespStreamMock(&[]ptesting.RespMock{ {Msg: "Bill"}, {Msg: "Gates"}, @@ -279,7 +277,7 @@ func TestLangRouter_ChatStream(t *testing.T) { ), providers.NewLangModel( "second", - ptesting.NewStreamProviderMock([]ptesting.RespStreamMock{ + ptesting.NewStreamProviderMock(nil, []ptesting.RespStreamMock{ ptesting.NewRespStreamMock(&[]ptesting.RespMock{ {Msg: "Knock"}, {Msg: "Knock"}, @@ -340,14 +338,14 @@ func TestLangRouter_ChatStream_FailOnFirst(t *testing.T) { langModels := []*providers.LanguageModel{ providers.NewLangModel( "first", - ptesting.NewStreamProviderMock(nil), + ptesting.NewStreamProviderMock(nil, nil), budget, *latConfig, 1, ), providers.NewLangModel( "second", - ptesting.NewStreamProviderMock([]ptesting.RespStreamMock{ + ptesting.NewStreamProviderMock(nil, []ptesting.RespStreamMock{ ptesting.NewRespStreamMock( &[]ptesting.RespMock{ {Msg: "Knock"}, @@ -410,9 +408,9 @@ func TestLangRouter_ChatStream_AllModelsUnavailable(t *testing.T) { langModels := []*providers.LanguageModel{ providers.NewLangModel( "first", - ptesting.NewStreamProviderMock([]ptesting.RespStreamMock{ + ptesting.NewStreamProviderMock(nil, []ptesting.RespStreamMock{ ptesting.NewRespStreamMock(&[]ptesting.RespMock{ - {Err: &clients.ErrProviderUnavailable}, + {Err: clients.ErrProviderUnavailable}, }), }), budget, @@ -421,9 +419,9 @@ func TestLangRouter_ChatStream_AllModelsUnavailable(t *testing.T) { ), providers.NewLangModel( "second", - ptesting.NewStreamProviderMock([]ptesting.RespStreamMock{ + ptesting.NewStreamProviderMock(nil, []ptesting.RespStreamMock{ ptesting.NewRespStreamMock(&[]ptesting.RespMock{ - {Err: &clients.ErrProviderUnavailable}, + {Err: clients.ErrProviderUnavailable}, }), }), budget, @@ -461,7 +459,7 @@ func TestLangRouter_ChatStream_AllModelsUnavailable(t *testing.T) { require.Nil(t, result.Chunk) require.NotNil(t, result.Error) - errs = append(errs, result.Error.ErrCode) + errs = append(errs, result.Error.Name) } require.Equal(t, []string{schemas.ModelUnavailable, schemas.ModelUnavailable, schemas.AllModelsUnavailable}, errs) diff --git a/pkg/routers/routing/least_latency.go b/pkg/routers/routing/least_latency.go index 78e04748..015c044e 100644 --- a/pkg/routers/routing/least_latency.go +++ b/pkg/routers/routing/least_latency.go @@ -5,9 +5,9 @@ import ( "sync/atomic" "time" - "glide/pkg/routers/latency" + "github.com/EinStack/glide/pkg/routers/latency" - "glide/pkg/providers" + "github.com/EinStack/glide/pkg/providers" ) const ( diff --git a/pkg/routers/routing/least_latency_test.go b/pkg/routers/routing/least_latency_test.go index 4b517afc..0ed9c51b 100644 --- a/pkg/routers/routing/least_latency_test.go +++ b/pkg/routers/routing/least_latency_test.go @@ -5,10 +5,11 @@ import ( "testing" "time" - ptesting "glide/pkg/providers/testing" + ptesting "github.com/EinStack/glide/pkg/providers/testing" + + "github.com/EinStack/glide/pkg/providers" "github.com/stretchr/testify/require" - "glide/pkg/providers" ) func TestLeastLatencyRouting_Warmup(t *testing.T) { diff --git a/pkg/routers/routing/priority.go b/pkg/routers/routing/priority.go index 1b0254ef..f895458c 100644 --- a/pkg/routers/routing/priority.go +++ b/pkg/routers/routing/priority.go @@ -3,7 +3,7 @@ package routing import ( "sync/atomic" - "glide/pkg/providers" + "github.com/EinStack/glide/pkg/providers" ) const ( diff --git a/pkg/routers/routing/priority_test.go b/pkg/routers/routing/priority_test.go index 2c4bcc1e..cee98c60 100644 --- a/pkg/routers/routing/priority_test.go +++ b/pkg/routers/routing/priority_test.go @@ -3,10 +3,11 @@ package routing import ( "testing" - ptesting "glide/pkg/providers/testing" + ptesting "github.com/EinStack/glide/pkg/providers/testing" + + "github.com/EinStack/glide/pkg/providers" "github.com/stretchr/testify/require" - "glide/pkg/providers" ) func TestPriorityRouting_PickModelsInOrder(t *testing.T) { diff --git a/pkg/routers/routing/round_robin.go b/pkg/routers/routing/round_robin.go index fb7e7e23..e5a0f927 100644 --- a/pkg/routers/routing/round_robin.go +++ b/pkg/routers/routing/round_robin.go @@ -3,7 +3,7 @@ package routing import ( "sync/atomic" - "glide/pkg/providers" + "github.com/EinStack/glide/pkg/providers" ) const ( diff --git a/pkg/routers/routing/round_robin_test.go b/pkg/routers/routing/round_robin_test.go index f8853ebe..fc34ec48 100644 --- a/pkg/routers/routing/round_robin_test.go +++ b/pkg/routers/routing/round_robin_test.go @@ -3,10 +3,11 @@ package routing import ( "testing" - ptesting "glide/pkg/providers/testing" + ptesting "github.com/EinStack/glide/pkg/providers/testing" + + "github.com/EinStack/glide/pkg/providers" "github.com/stretchr/testify/require" - "glide/pkg/providers" ) func TestRoundRobinRouting_PickModelsSequentially(t *testing.T) { diff --git a/pkg/routers/routing/strategies.go b/pkg/routers/routing/strategies.go index 1cd3aab8..56f03676 100644 --- a/pkg/routers/routing/strategies.go +++ b/pkg/routers/routing/strategies.go @@ -3,7 +3,7 @@ package routing import ( "errors" - "glide/pkg/providers" + "github.com/EinStack/glide/pkg/providers" ) var ErrNoHealthyModels = errors.New("no healthy models found") diff --git a/pkg/routers/routing/weighted_round_robin.go b/pkg/routers/routing/weighted_round_robin.go index 3e06a601..2e028408 100644 --- a/pkg/routers/routing/weighted_round_robin.go +++ b/pkg/routers/routing/weighted_round_robin.go @@ -3,7 +3,7 @@ package routing import ( "sync" - "glide/pkg/providers" + "github.com/EinStack/glide/pkg/providers" ) const ( diff --git a/pkg/routers/routing/weighted_round_robin_test.go b/pkg/routers/routing/weighted_round_robin_test.go index af258bb3..f4b59bb3 100644 --- a/pkg/routers/routing/weighted_round_robin_test.go +++ b/pkg/routers/routing/weighted_round_robin_test.go @@ -3,10 +3,11 @@ package routing import ( "testing" - ptesting "glide/pkg/providers/testing" + ptesting "github.com/EinStack/glide/pkg/providers/testing" + + "github.com/EinStack/glide/pkg/providers" "github.com/stretchr/testify/require" - "glide/pkg/providers" ) func TestWRoundRobinRouting_RoutingDistribution(t *testing.T) { diff --git a/pkg/telemetry/telemetry.go b/pkg/telemetry/telemetry.go index ec85fec4..94f4a77c 100644 --- a/pkg/telemetry/telemetry.go +++ b/pkg/telemetry/telemetry.go @@ -1,16 +1,32 @@ package telemetry -import "go.uber.org/zap" +import ( + "context" + "os" + + "github.com/google/uuid" + "go.opentelemetry.io/contrib/exporters/autoexport" + "go.opentelemetry.io/contrib/propagators/b3" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/sdk/metric" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/resource" + "go.opentelemetry.io/otel/sdk/trace" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.24.0" + "go.uber.org/zap" +) type Config struct { - LogConfig *LogConfig `yaml:"logging" validate:"required"` - // TODO: add OTEL config + LogConfig *LogConfig `yaml:"logging" validate:"required"` + Resource map[string]string `yaml:"resource"` } type Telemetry struct { Config *Config Logger *zap.Logger - // TODO: add OTEL meter, tracer } func (t Telemetry) L() *zap.Logger { @@ -18,8 +34,17 @@ func (t Telemetry) L() *zap.Logger { } func DefaultConfig() *Config { + instance := os.Getenv("POD_NAME") + if instance == "" { + instance = uuid.New().String() + } + return &Config{ LogConfig: DefaultLogConfig(), + Resource: map[string]string{ + string(semconv.ServiceNameKey): "glide", + string(semconv.ServiceInstanceIDKey): instance, + }, } } @@ -29,6 +54,45 @@ func NewTelemetry(cfg *Config) (*Telemetry, error) { return nil, err } + resourceAttr := make([]attribute.KeyValue, 0, len(cfg.Resource)) + + for k, v := range cfg.Resource { + resourceAttr = append(resourceAttr, attribute.String(k, v)) + } + + resource := resource.NewWithAttributes( + semconv.SchemaURL, + resourceAttr..., + ) + + spanExporter, err := newSpanExporter() + if err != nil { + return nil, err + } + + tp := sdktrace.NewTracerProvider( + sdktrace.WithResource(resource), + sdktrace.WithSampler(sdktrace.AlwaysSample()), + sdktrace.WithBatcher(spanExporter), + ) + otel.SetTracerProvider(tp) + otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, + propagation.Baggage{}, b3.New())) + + metricsReader, err := newMetricReader() + if err != nil { + return nil, err + } + + provider := sdkmetric.NewMeterProvider( + sdkmetric.WithReader( + metricsReader, + ), + sdkmetric.WithResource(resource), + ) + + otel.SetMeterProvider(provider) + return &Telemetry{ Config: cfg, Logger: logger, @@ -46,3 +110,31 @@ func NewTelemetryMock() *Telemetry { Logger: NewLoggerMock(), } } + +func newMetricReader() (sdkmetric.Reader, error) { + return autoexport.NewMetricReader(context.Background(), + autoexport.WithFallbackMetricReader(func(_ context.Context) (sdkmetric.Reader, error) { + return metric.NewManualReader(), nil + }), + ) +} + +func newSpanExporter() (sdktrace.SpanExporter, error) { + return autoexport.NewSpanExporter(context.Background(), autoexport.WithFallbackSpanExporter( + func(_ context.Context) (sdktrace.SpanExporter, error) { + return noopSpanExporter{}, nil + }, + )) +} + +type noopSpanExporter struct{} + +var _ trace.SpanExporter = noopSpanExporter{} + +func (e noopSpanExporter) ExportSpans(_ context.Context, _ []trace.ReadOnlySpan) error { + return nil +} + +func (e noopSpanExporter) Shutdown(_ context.Context) error { + return nil +} diff --git a/pkg/telemetry/telemetry_test.go b/pkg/telemetry/telemetry_test.go index 2f69ef89..7ee08801 100644 --- a/pkg/telemetry/telemetry_test.go +++ b/pkg/telemetry/telemetry_test.go @@ -1,12 +1,32 @@ package telemetry import ( + "context" "testing" "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/sdk/metric" ) func TestTelemetry_Creation(t *testing.T) { _, err := NewTelemetry(DefaultConfig()) require.NoError(t, err) } + +func TestDefaults_noopExporters(t *testing.T) { + // By default all otel providers must be noop. Since we don't have otel setup + // in test environment, this test ensures all providers are noop. + mr, err := newMetricReader() + if err != nil { + t.Fatal(err) + } + // ensures we have a noop metric.ManualReader + _ = mr.(*metric.ManualReader).Shutdown(context.Background()) + + se, err := newSpanExporter() + if err != nil { + t.Fatal(err) + } + // ensures we have a noopSpanExporter + _ = se.(noopSpanExporter).Shutdown(context.Background()) +} diff --git a/tools/otel-col-config.yaml b/tools/otel-col-config.yaml new file mode 100644 index 00000000..f0e8ca68 --- /dev/null +++ b/tools/otel-col-config.yaml @@ -0,0 +1,35 @@ +receivers: + otlp: + protocols: + grpc: + +exporters: + prometheusremotewrite: + endpoint: "http://victoriametrics:8428/api/v1/write" + + otlp: + endpoint: jaeger-all-in-one:4317 + tls: + insecure: true + +processors: + batch: + +extensions: + health_check: + pprof: + endpoint: :1888 + zpages: + endpoint: :55679 + +service: + extensions: [ pprof, zpages, health_check ] + pipelines: + traces: + receivers: [ otlp ] + processors: [ batch ] + exporters: [ otlp ] + metrics: + receivers: [ otlp ] + processors: [ batch ] + exporters: [ prometheusremotewrite ] From 85d02b39afbbfce5a252c74f1aa4d3296a100ca1 Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Mon, 24 Jun 2024 21:13:12 +0300 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=93=9DAdded=20information=20about=20c?= =?UTF-8?q?urrent=20release=20procedure?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- RELEASE.md | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 RELEASE.md diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 00000000..f5259685 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,71 @@ +# Release + +This document explains the current release procedure for the Glide project. + +A person that handles the release is called the release manager. + +The release version should be picked based on the previous version and changes that are going to be released: +- If the previous version was `0.0.3` and changeset doesn't have breaking changes in API, the next version may be either `0.0.4-rc.1`. +- If the previous version was `0.0.3-rc.2` and changeset doesn't have breaking changes in API, the next version may be either `0.0.3-rc.3` or `0.0.3`. +- if the previous version was `0.0.3` and changeset has breaking changes in API, the next version may be either `0.1.0-rc.1` or `0.1.0`. + +It's encouraged to have a release candidate as an intermediate step in the releasing the "stable" version. + +## The release process + +The following is step-by-step instruction. + +### The release PR + +The release manager creates a new pull request from the `develop` branch into the `main`. + +### Collect changelog + +The changeset from the PR should be reviewed and represented as a changelog in the `CHANGELOG.md` file. + +Git can be helpful to summarize changes: + +```bash +git log --pretty=format:"%s (%an)" {LAST_VERSION_TAG}..HEAD +``` + +Sort out all changes to the categories they belong to. + +### Update the release PR description + +Use the created changelog to update the PR description. + +### Merge the release PR + +Once all checks are green on the Release PR, you can merge it into the main. +When squashing the pull request, please specify the same changelog you have added to the PR description. + +### Tag the merge commit + +Tag the merge commit in the main branch using the release version like `0.1.0-rc.1`. + +That should trigger a deployment pipeline that can be checked under https://github.com/EinStack/glide/actions. + +Wait until the pipeline is done or failed. + +### Create a GitHub release + +The release manager then creates a release in GitHub for the released version. +The GitHub release should contain the same changelog message we have used in the release PR description. + +The release should be marked as a pre-release if the version is a release candidate or a stable release otherwise. + +Feel free to announce the release via creating a discussion (there is a checkbox for that on the new GitHub release form). + +### Spread a word about the release + +The release manager should spread a word about the release in the Discord community space. + +Please use the `#announcements` channel for announcing stable releases. +You can use `#general` to announce release candidates. + +Be sure to do shutouts for people who spend their time improving the project. + +| Releases | Release Manager | +|------------------|-----------------| +| 0.0.1-0.1.0-rc.1 | @roma-glushko |

K{c|1Zw#iz70k&po(Y>Efff2j4`!g8LpwKFt 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[Jn$MO7@ee*NZ| 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%0DFwV!nzFFB7O7C)& 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