cauto vor 1 Jahr
Commit
c37955476f
44 geänderte Dateien mit 1770 neuen und 0 gelöschten Zeilen
  1. 1 0
      .gitattributes
  2. 14 0
      .gitignore
  3. 74 0
      Makefile
  4. 9 0
      README.MD
  5. 12 0
      api/v1/hello.go
  6. 5 0
      go.mod
  7. 85 0
      go.sum
  8. 462 0
      gpt/gpt.go
  9. 307 0
      gpt/model.go
  10. 69 0
      gpt/options.go
  11. 11 0
      gpt/utils.go
  12. 4 0
      hack/config.yaml
  13. 48 0
      internal/cmd/cmd.go
  14. 1 0
      internal/consts/consts.go
  15. 6 0
      internal/consts/consts_openapi.go
  16. 65 0
      internal/controller/hello.go
  17. 0 0
      internal/dao/.gitkeep
  18. 0 0
      internal/logic/.gitkeep
  19. 0 0
      internal/model/.gitkeep
  20. 0 0
      internal/model/do/.gitkeep
  21. 0 0
      internal/model/entity/.gitkeep
  22. 1 0
      internal/packed/packed.go
  23. 0 0
      internal/service/.gitkeep
  24. 13 0
      main.go
  25. 84 0
      manifest/config/config.yaml
  26. 21 0
      manifest/deploy/kustomize/base/deployment.yaml
  27. 8 0
      manifest/deploy/kustomize/base/kustomization.yaml
  28. 12 0
      manifest/deploy/kustomize/base/service.yaml
  29. 14 0
      manifest/deploy/kustomize/overlays/develop/configmap.yaml
  30. 10 0
      manifest/deploy/kustomize/overlays/develop/deployment.yaml
  31. 14 0
      manifest/deploy/kustomize/overlays/develop/kustomization.yaml
  32. 16 0
      manifest/docker/Dockerfile
  33. 8 0
      manifest/docker/docker.sh
  34. 0 0
      resource/i18n/.gitkeep
  35. 345 0
      resource/log/server/2023-03-30.log
  36. 21 0
      resource/log/server/access-20230330.log
  37. 0 0
      resource/public/html/.gitkeep
  38. 0 0
      resource/public/plugin/.gitkeep
  39. 0 0
      resource/public/resource/css/.gitkeep
  40. 0 0
      resource/public/resource/image/.gitkeep
  41. 0 0
      resource/public/resource/js/.gitkeep
  42. 0 0
      resource/template/.gitkeep
  43. 30 0
      router/router.go
  44. 0 0
      utility/.gitkeep

+ 1 - 0
.gitattributes

@@ -0,0 +1 @@
+* linguist-language=GO

+ 14 - 0
.gitignore

@@ -0,0 +1,14 @@
+.buildpath
+.hgignore.swp
+.project
+.orig
+.swp
+.idea/
+.settings/
+.vscode/
+bin/
+**/.DS_Store
+main
+output/
+manifest/output/
+temp/

+ 74 - 0
Makefile

@@ -0,0 +1,74 @@
+ROOT_DIR    = $(shell pwd)
+NAMESPACE   = "default"
+DEPLOY_NAME = "template-single"
+DOCKER_NAME = "template-single"
+
+# Install/Update to the latest CLI tool.
+.PHONY: cli
+cli:
+	@set -e; \
+	wget -O gf https://github.com/gogf/gf/releases/latest/download/gf_$(shell go env GOOS)_$(shell go env GOARCH) && \
+	chmod +x gf && \
+	./gf install -y && \
+	rm ./gf
+
+
+# Check and install CLI tool.
+.PHONY: cli.install
+cli.install:
+	@set -e; \
+	gf -v > /dev/null 2>&1 || if [[ "$?" -ne "0" ]]; then \
+  		echo "GoFame CLI is not installed, start proceeding auto installation..."; \
+		make cli; \
+	fi;
+
+
+# Generate Go files for DAO/DO/Entity.
+.PHONY: dao
+dao: cli.install
+	@gf gen dao
+
+# Generate Go files for Service.
+.PHONY: service
+service: cli.install
+	@gf gen service
+
+# Build image, deploy image and yaml to current kubectl environment and make port forward to local machine.
+.PHONY: start
+start:
+	@set -e; \
+	make image; \
+	make deploy; \
+	make port;
+
+# Build docker image.
+.PHONY: image
+image: cli.install
+	$(eval _TAG  = $(shell git log -1 --format="%cd.%h" --date=format:"%Y%m%d%H%M%S"))
+ifneq (, $(shell git status --porcelain 2>/dev/null))
+	$(eval _TAG  = $(_TAG).dirty)
+endif
+	$(eval _TAG  = $(if ${TAG},  ${TAG}, $(_TAG)))
+	$(eval _PUSH = $(if ${PUSH}, ${PUSH}, ))
+	@gf docker -p -b "-a amd64 -s linux -p temp" -tn $(DOCKER_NAME):${_TAG};
+
+
+# Build docker image and automatically push to docker repo.
+.PHONY: image.push
+image.push:
+	@make image PUSH=-p;
+
+
+# Deploy image and yaml to current kubectl environment.
+.PHONY: deploy
+deploy:
+	$(eval _TAG = $(if ${TAG},  ${TAG}, develop))
+
+	@set -e; \
+	mkdir -p $(ROOT_DIR)/temp/kustomize;\
+	cd $(ROOT_DIR)/manifest/deploy/kustomize/overlays/${_TAG};\
+	kustomize build > $(ROOT_DIR)/temp/kustomize.yaml;\
+	kubectl   apply -f $(ROOT_DIR)/temp/kustomize.yaml; \
+	kubectl   patch -n $(NAMESPACE) deployment/$(DEPLOY_NAME) -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"$(shell date +%s)\"}}}}}";
+
+

+ 9 - 0
README.MD

@@ -0,0 +1,9 @@
+# GoFrame Template For SingleRepo
+
+Project Makefile Commands: 
+- `make cli`: Install or Update to the latest GoFrame CLI tool.
+- `make dao`: Generate go files for `Entity/DAO/DO` according to the configuration file from `hack` folder.
+- `make service`: Parse `logic` folder to generate interface go files into `service` folder.
+- `make image TAG=xxx`: Run `docker build` to build image according `manifest/docker`.
+- `make image.push TAG=xxx`: Run `docker build` and `docker push` to build and push image according `manifest/docker`.
+- `make deploy TAG=xxx`: Run `kustomize build` to build and deploy deployment to kubernetes server group according `manifest/deploy`.

+ 12 - 0
api/v1/hello.go

@@ -0,0 +1,12 @@
+package v1
+
+import (
+	"github.com/gogf/gf/v2/frame/g"
+)
+
+type HelloReq struct {
+	g.Meta `path:"/hello" tags:"Hello" method:"post" summary:"You first hello api"`
+}
+type HelloRes struct {
+	g.Meta `mime:"application/json" example:"json"`
+}

+ 5 - 0
go.mod

@@ -0,0 +1,5 @@
+module go-gpt
+
+go 1.15
+
+require github.com/gogf/gf/v2 v2.3.1

+ 85 - 0
go.sum

@@ -0,0 +1,85 @@
+github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
+github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
+github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
+github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
+github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
+github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
+github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
+github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+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/gogf/gf/v2 v2.3.1 h1:uptCJK47N6KSRwTBnFAqBWYnYa/OXBkZ0OlhO9CK7bQ=
+github.com/gogf/gf/v2 v2.3.1/go.mod h1:tsbmtwcAl2chcYoq/fP9W2FZf06aw4i89X34nbSHo9Y=
+github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
+github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
+github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
+github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
+github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
+github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
+github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
+github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
+github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
+github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
+github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
+github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
+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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+go.opentelemetry.io/otel v1.7.0 h1:Z2lA3Tdch0iDcrhJXDIlC94XE+bxok1F9B+4Lz/lGsM=
+go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
+go.opentelemetry.io/otel/sdk v1.7.0 h1:4OmStpcKVOfvDOgCt7UriAPtKolwIhxpnSNI/yK+1B0=
+go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU=
+go.opentelemetry.io/otel/trace v1.7.0 h1:O37Iogk1lEkMRXewVtZ1BBTVn5JEp8GrJvP92bJqC6o=
+go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
+golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObFOHXYypgGjnGno25RDwn3Y=
+golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

+ 462 - 0
gpt/gpt.go

@@ -0,0 +1,462 @@
+// Package gpt provides a client for the OpenAI GPT-3 API
+package gpt
+
+import (
+	"bufio"
+	"bytes"
+	"context"
+	"encoding/json"
+	"fmt"
+	"io"
+	"net/http"
+	"time"
+)
+
+// Define GPT-3 Engine Types
+const (
+	TextAda001Engine     = "text-ada-001"     // TextAda001Engine Text Ada 001
+	TextBabbage001Engine = "text-babbage-001" // TextBabbage001Engine Text Babbage 001
+	TextCurie001Engine   = "text-curie-001"   // TextCurie001Engine Text Curie 001
+	TextDavinci001Engine = "text-davinci-001" // TextDavinci001Engine Text Davinci 001
+	TextDavinci002Engine = "text-davinci-002" // TextDavinci002Engine Text Davinci 002
+	TextDavinci003Engine = "text-davinci-003" // TextDavinci003Engine Text Davinci 003
+	AdaEngine            = "ada"              // AdaEngine Ada
+	BabbageEngine        = "babbage"          // BabbageEngine Babbage
+	CurieEngine          = "curie"            // CurieEngine Curie
+	DavinciEngine        = "davinci"          // DavinciEngine Davinci
+	DefaultEngine        = DavinciEngine      // DefaultEngine Default Engine
+)
+
+const (
+	GPT4                      = "gpt4"                          // GPT4 GPT-4
+	GPT3Dot5Turbo             = "gpt-3.5-turbo"                 // GPT3Dot5Turbo GPT-3.5 Turbo
+	GPT3Dot5Turbo0301         = "gpt-3.5-turbo-0301"            // GPT3Dot5Turbo0301 GPT-3.5 Turbo 0301
+	TextSimilarityAda001      = "text-similarity-ada-001"       // TextSimilarityAda001 Text Similarity Ada 001
+	TextSimilarityBabbage001  = "text-similarity-babbage-001"   // TextSimilarityBabbage001 Text Similarity Babbage 001
+	TextSimilarityCurie001    = "text-similarity-curie-001"     // TextSimilarityCurie001 Text Similarity Curie 001
+	TextSimilarityDavinci001  = "text-similarity-davinci-001"   // TextSimilarityDavinci001 Text Similarity Davinci 001
+	TextSearchAdaDoc001       = "text-search-ada-doc-001"       // TextSearchAdaDoc001 Text Search Ada Doc 001
+	TextSearchAdaQuery001     = "text-search-ada-query-001"     // TextSearchAdaQuery001 Text Search Ada Query 001
+	TextSearchBabbageDoc001   = "text-search-babbage-doc-001"   // TextSearchBabbageDoc001 Text Search Babbage Doc 001
+	TextSearchBabbageQuery001 = "text-search-babbage-query-001" // TextSearchBabbageQuery001 Text Search Babbage Query 001
+	TextSearchCurieDoc001     = "text-search-curie-doc-001"     // TextSearchCurieDoc001 Text Search Curie Doc 001
+	TextSearchCurieQuery001   = "text-search-curie-query-001"   // TextSearchCurieQuery001 Text Search Curie Query 001
+	TextSearchDavinciDoc001   = "text-search-davinci-doc-001"   // TextSearchDavinciDoc001 Text Search Davinci Doc 001
+	TextSearchDavinciQuery001 = "text-search-davinci-query-001" // TextSearchDavinciQuery001 Text Search Davinci Query 001
+	CodeSearchAdaCode001      = "code-search-ada-code-001"      // CodeSearchAdaCode001 Code Search Ada Code 001
+	CodeSearchAdaText001      = "code-search-ada-text-001"      // CodeSearchAdaText001 Code Search Ada Text 001
+	CodeSearchBabbageCode001  = "code-search-babbage-code-001"  // CodeSearchBabbageCode001 Code Search Babbage Code 001
+	CodeSearchBabbageText001  = "code-search-babbage-text-001"  // CodeSearchBabbageText001 Code Search Babbage Text 001
+	TextEmbeddingAda002       = "text-embedding-ada-002"        // TextEmbeddingAda002 Text Embedding Ada 002
+)
+
+const (
+	defaultBaseURL        = "https://api.openai.com/v1"
+	defaultUserAgent      = "go-gpt3"
+	defaultTimeoutSeconds = 30
+)
+
+// Image sizes defined by the OpenAI API.
+const (
+	CreateImageSize256x256   = "256x256"   // CreateImageSize256x256 256x256
+	CreateImageSize512x512   = "512x512"   // CreateImageSize512x512 512x512
+	CreateImageSize1024x1024 = "1024x1024" // CreateImageSize1024x1024 1024x1024
+
+	CreateImageResponseFormatURL     = "url"      // CreateImageResponseFormatURL URL
+	CreateImageResponseFormatB64JSON = "b64_json" // CreateImageResponseFormatB64JSON B64 JSON
+)
+
+// Client is an API client to communicate with the OpenAI gpt-3 APIs
+type Client interface {
+	// Engines lists the currently available engines, and provides basic information about each
+	// option such as the owner and availability.
+	Engines(ctx context.Context) (*EnginesResponse, error)
+
+	// Engine retrieves an engine instance, providing basic information about the engine such
+	// as the owner and availability.
+	Engine(ctx context.Context, engine string) (*EngineObject, error)
+
+	// ChatCompletion creates a completion with the Chat completion endpoint which
+	// is what powers the ChatGPT experience.
+	ChatCompletion(ctx context.Context, request *ChatCompletionRequest) (*ChatCompletionResponse, error)
+
+	// ChatCompletionStream creates a completion with the Chat completion endpoint which
+	// is what powers the ChatGPT experience.
+	ChatCompletionStream(ctx context.Context, request *ChatCompletionRequest, onData func(*ChatCompletionStreamResponse)) error
+
+	// Completion creates a completion with the default engine. This is the main endpoint of the API
+	// which auto-completes based on the given prompt.
+	Completion(ctx context.Context, request *CompletionRequest) (*CompletionResponse, error)
+
+	// CompletionStream creates a completion with the default engine and streams the results through
+	// multiple calls to onData.
+	CompletionStream(ctx context.Context, request *CompletionRequest, onData func(*CompletionResponse)) error
+
+	// CompletionWithEngine is the same as Completion except allows overriding the default engine on the client
+	CompletionWithEngine(ctx context.Context, request *CompletionRequest) (*CompletionResponse, error)
+
+	// CompletionStreamWithEngine is the same as CompletionStream allows overriding the default engine on the client
+	CompletionStreamWithEngine(ctx context.Context, request *CompletionRequest, onData func(*CompletionResponse)) error
+
+	// Edits is given a prompt and an instruction, the model will return an edited version of the prompt.
+	Edits(ctx context.Context, request *EditsRequest) (*EditsResponse, error)
+
+	// Search performs a semantic search over a list of documents with the default engine.
+	Search(ctx context.Context, request *SearchRequest) (*SearchResponse, error)
+
+	// SearchWithEngine performs a semantic search over a list of documents with the specified engine.
+	SearchWithEngine(ctx context.Context, engine string, request *SearchRequest) (*SearchResponse, error)
+
+	// Embeddings Returns an embedding using the provided request.
+	Embeddings(ctx context.Context, request *EmbeddingsRequest) (*EmbeddingsResponse, error)
+
+	// Image returns an image using the provided request.
+	Image(ctx context.Context, request *ImageRequest) (*ImageResponse, error)
+}
+
+type client struct {
+	baseURL       string
+	apiKey        string
+	userAgent     string
+	httpClient    *http.Client
+	defaultEngine string
+	idOrg         string
+}
+
+// NewClient returns a new OpenAI GPT-3 API client. An APIKey is required to use the client
+func NewClient(apiKey string, options ...ClientOption) Client {
+	httpClient := &http.Client{
+		Timeout: defaultTimeoutSeconds * time.Second,
+	}
+	cli := &client{
+		userAgent:     defaultUserAgent,
+		apiKey:        apiKey,
+		baseURL:       defaultBaseURL,
+		httpClient:    httpClient,
+		defaultEngine: DefaultEngine,
+		idOrg:         "",
+	}
+	for _, opt := range options {
+		cli = opt.apply(cli)
+	}
+	return cli
+}
+
+// Engines lists the currently available engines, and provides basic information about each
+// option such as the owner and availability.
+func (c *client) Engines(ctx context.Context) (*EnginesResponse, error) {
+	req, err := c.newRequest(ctx, "GET", "/engines", nil)
+	if err != nil {
+		return nil, err
+	}
+	rsp, err := c.performRequest(req)
+	if err != nil {
+		return nil, err
+	}
+	output := new(EnginesResponse)
+	if err := getResponseObject(rsp, output); err != nil {
+		return nil, err
+	}
+	return output, nil
+}
+
+// Engine retrieves an engine instance, providing basic information about the engine such
+// as the owner and availability.
+func (c *client) Engine(ctx context.Context, engine string) (*EngineObject, error) {
+	req, err := c.newRequest(ctx, "GET", fmt.Sprintf("/engines/%s", engine), nil)
+	if err != nil {
+		return nil, err
+	}
+	rsp, err := c.performRequest(req)
+	if err != nil {
+		return nil, err
+	}
+	output := new(EngineObject)
+	if err := getResponseObject(rsp, output); err != nil {
+		return nil, err
+	}
+	return output, nil
+}
+
+// ChatCompletion creates a completion with the Chat completion endpoint which
+// is what powers the ChatGPT experience.
+func (c *client) ChatCompletion(ctx context.Context, request *ChatCompletionRequest) (*ChatCompletionResponse, error) {
+	if request.Model == "" {
+		request.Model = GPT3Dot5Turbo
+	}
+	request.Stream = false
+	req, err := c.newRequest(ctx, "POST", "/chat/completions", &request)
+	if err != nil {
+		return nil, err
+	}
+	rsp, err := c.performRequest(req)
+	if err != nil {
+		return nil, err
+	}
+	output := new(ChatCompletionResponse)
+	if err := getResponseObject(rsp, output); err != nil {
+		return nil, err
+	}
+	return output, nil
+}
+
+// ChatCompletionStream creates a completion with the Chat completion endpoint which
+// is what powers the ChatGPT experience.
+func (c *client) ChatCompletionStream(ctx context.Context, request *ChatCompletionRequest, onData func(*ChatCompletionStreamResponse)) error {
+	if request.Model == "" {
+		request.Model = GPT3Dot5Turbo
+	}
+	request.Stream = true
+	req, err := c.newRequest(ctx, "POST", "/chat/completions", request)
+	if err != nil {
+		return err
+	}
+	rsp, err := c.performRequest(req)
+	if err != nil {
+		return err
+	}
+	reader := bufio.NewReader(rsp.Body)
+	defer rsp.Body.Close()
+	for {
+		line, err := reader.ReadBytes('\n')
+		if err != nil {
+			return err
+		}
+		// make sure there isn't any extra whitespace before or after
+		line = bytes.TrimSpace(line)
+		// the completion API only returns data events
+		if !bytes.HasPrefix(line, dataPrefix) {
+			continue
+		}
+		line = bytes.TrimPrefix(line, dataPrefix)
+		// the stream is completed when terminated by [DONE]
+		if bytes.HasPrefix(line, doneSequence) {
+			break
+		}
+		output := new(ChatCompletionStreamResponse)
+		if err := json.Unmarshal(line, output); err != nil {
+			return fmt.Errorf("invalid json stream data: %v", err)
+		}
+		onData(output)
+	}
+	return nil
+}
+
+// Completion creates a completion with the default engine.
+func (c *client) Completion(ctx context.Context, request *CompletionRequest) (*CompletionResponse, error) {
+	return c.CompletionWithEngine(ctx, request)
+}
+
+// CompletionWithEngine creates a completion with the specified engine.
+func (c *client) CompletionWithEngine(ctx context.Context, request *CompletionRequest) (*CompletionResponse, error) {
+	request.Stream = false
+	req, err := c.newRequest(ctx, "POST", "/completions", &request)
+	if err != nil {
+		return nil, err
+	}
+	rsp, err := c.performRequest(req)
+	if err != nil {
+		return nil, err
+	}
+	output := new(CompletionResponse)
+	if err := getResponseObject(rsp, output); err != nil {
+		return nil, err
+	}
+	return output, nil
+}
+
+// CompletionStream creates a completion with the default engine.
+func (c *client) CompletionStream(ctx context.Context, request *CompletionRequest,
+	onData func(*CompletionResponse)) error {
+	return c.CompletionStreamWithEngine(ctx, request, onData)
+}
+
+var (
+	dataPrefix   = []byte("data: ")
+	doneSequence = []byte("[DONE]")
+)
+
+// CompletionStreamWithEngine creates a completion with the specified engine.
+func (c *client) CompletionStreamWithEngine(ctx context.Context, request *CompletionRequest,
+	onData func(*CompletionResponse)) error {
+	request.Stream = true
+	req, err := c.newRequest(ctx, "POST", "/completions", &request)
+	if err != nil {
+		return err
+	}
+	rsp, err := c.performRequest(req)
+	if err != nil {
+		return err
+	}
+	reader := bufio.NewReader(rsp.Body)
+	defer rsp.Body.Close()
+	for {
+		line, err := reader.ReadBytes('\n')
+		if err != nil {
+			return err
+		}
+		// make sure there isn't any extra whitespace before or after
+		line = bytes.TrimSpace(line)
+		// the completion API only returns data events
+		if !bytes.HasPrefix(line, dataPrefix) {
+			continue
+		}
+		line = bytes.TrimPrefix(line, dataPrefix)
+		// the stream is completed when terminated by [DONE]
+		if bytes.HasPrefix(line, doneSequence) {
+			break
+		}
+		output := new(CompletionResponse)
+		if err := json.Unmarshal(line, output); err != nil {
+			return fmt.Errorf("invalid json stream data: %v", err)
+		}
+		onData(output)
+	}
+	return nil
+}
+
+// Edits is given a prompt and an instruction, the model will return an edited version of the prompt.
+func (c *client) Edits(ctx context.Context, request *EditsRequest) (*EditsResponse, error) {
+	req, err := c.newRequest(ctx, "POST", "/edits", &request)
+	if err != nil {
+		return nil, err
+	}
+	rsp, err := c.performRequest(req)
+	if err != nil {
+		return nil, err
+	}
+	output := new(EditsResponse)
+	if err := getResponseObject(rsp, output); err != nil {
+		return nil, err
+	}
+	return output, nil
+}
+
+// Search creates a search with the default engine.
+func (c *client) Search(ctx context.Context, request *SearchRequest) (*SearchResponse, error) {
+	return c.SearchWithEngine(ctx, c.defaultEngine, request)
+}
+
+// SearchWithEngine performs a semantic search over a list of documents with the specified engine.
+func (c *client) SearchWithEngine(ctx context.Context, engine string, request *SearchRequest) (*SearchResponse, error) {
+	req, err := c.newRequest(ctx, "POST", fmt.Sprintf("/engines/%s/search", engine), &request)
+	if err != nil {
+		return nil, err
+	}
+	rsp, err := c.performRequest(req)
+	if err != nil {
+		return nil, err
+	}
+	output := new(SearchResponse)
+	if err := getResponseObject(rsp, output); err != nil {
+		return nil, err
+	}
+	return output, nil
+}
+
+// Embeddings creates text embeddings for a supplied slice of inputs with a provided model.
+// See: https://beta.openai.com/docs/api-reference/embeddings
+func (c *client) Embeddings(ctx context.Context, request *EmbeddingsRequest) (*EmbeddingsResponse, error) {
+	req, err := c.newRequest(ctx, "POST", "/embeddings", &request)
+	if err != nil {
+		return nil, err
+	}
+	rsp, err := c.performRequest(req)
+	if err != nil {
+		return nil, err
+	}
+	output := EmbeddingsResponse{}
+	if err := getResponseObject(rsp, &output); err != nil {
+		return nil, err
+	}
+	return &output, nil
+}
+
+// Image creates an image
+func (c *client) Image(ctx context.Context, request *ImageRequest) (*ImageResponse, error) {
+	req, err := c.newRequest(ctx, "POST", "/images/generations", &request)
+	if err != nil {
+		return nil, err
+	}
+	rsp, err := c.performRequest(req)
+	if err != nil {
+		return nil, err
+	}
+	output := ImageResponse{}
+	if err := getResponseObject(rsp, &output); err != nil {
+		return nil, err
+	}
+	return &output, nil
+}
+
+func (c *client) performRequest(req *http.Request) (*http.Response, error) {
+	rsp, err := c.httpClient.Do(req)
+	if err != nil {
+		return nil, err
+	}
+	if err := checkForSuccess(rsp); err != nil {
+		return nil, err
+	}
+	return rsp, nil
+}
+
+// checkForSuccess returns an error if this response includes an error.
+func checkForSuccess(rsp *http.Response) error {
+	if rsp.StatusCode >= 200 && rsp.StatusCode < 300 {
+		return nil
+	}
+	defer rsp.Body.Close()
+	data, err := io.ReadAll(rsp.Body)
+	if err != nil {
+		return fmt.Errorf("failed to read from body: %w", err)
+	}
+	var result APIErrorResponse
+	if err := json.Unmarshal(data, &result); err != nil {
+		// if we can't decode the json error then create an unexpected error
+		apiError := APIError{
+			StatusCode: rsp.StatusCode,
+			Type:       "Unexpected",
+			Message:    string(data),
+		}
+		return apiError
+	}
+	result.Error.StatusCode = rsp.StatusCode
+	return result.Error
+}
+
+func getResponseObject(rsp *http.Response, v interface{}) error {
+	defer rsp.Body.Close()
+	if err := json.NewDecoder(rsp.Body).Decode(v); err != nil {
+		return fmt.Errorf("invalid json response: %w", err)
+	}
+	return nil
+}
+
+func jsonBodyReader(body interface{}) (io.Reader, error) {
+	if body == nil {
+		return bytes.NewBuffer(nil), nil
+	}
+	raw, err := json.Marshal(body)
+	if err != nil {
+		return nil, fmt.Errorf("failed encoding json: %w", err)
+	}
+	return bytes.NewBuffer(raw), nil
+}
+
+func (c *client) newRequest(ctx context.Context, method, path string, payload interface{}) (*http.Request, error) {
+	bodyReader, err := jsonBodyReader(payload)
+	if err != nil {
+		return nil, err
+	}
+	url := c.baseURL + path
+	req, err := http.NewRequestWithContext(ctx, method, url, bodyReader)
+	if err != nil {
+		return nil, err
+	}
+	if len(c.idOrg) > 0 {
+		req.Header.Set("OpenAI-Organization", c.idOrg)
+	}
+	req.Header.Set("Content-type", "application/json")
+	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.apiKey))
+	return req, nil
+}

+ 307 - 0
gpt/model.go

@@ -0,0 +1,307 @@
+package gpt
+
+import "fmt"
+
+// APIError represents an error that occurred on an API
+type APIError struct {
+	StatusCode int    `json:"status_code"`
+	Message    string `json:"message"`
+	Type       string `json:"type"`
+}
+
+// Error returns a string representation of the error
+func (e APIError) Error() string {
+	return fmt.Sprintf("[%d:%s] %s", e.StatusCode, e.Type, e.Message)
+}
+
+// APIErrorResponse is the full error response that has been returned by an API.
+type APIErrorResponse struct {
+	Error APIError `json:"error"`
+}
+
+// EngineObject contained in an engine repose
+type EngineObject struct {
+	ID     string `json:"id"`
+	Object string `json:"object"`
+	Owner  string `json:"owner"`
+	Ready  bool   `json:"ready"`
+}
+
+// EnginesResponse is returned from the Engines API
+type EnginesResponse struct {
+	Data   []EngineObject `json:"data"`
+	Object string         `json:"object"`
+}
+
+// ChatCompletionRequestMessage is a message to use as the context for the chat completion API
+type ChatCompletionRequestMessage struct {
+	// Role is the role is the role of the message. Can be "system", "user", or "assistant"
+	Role string `json:"role"`
+	// Content is the content of the message
+	Content string `json:"content"`
+}
+
+// ChatCompletionRequest is a request for the chat completion API
+type ChatCompletionRequest struct {
+	// Model is the name of the model to use. If not specified, will default to gpt-3.5-turbo.
+	Model string `json:"model"`
+	// Messages is a list of messages to use as the context for the chat completion.
+	Messages []ChatCompletionRequestMessage `json:"messages"`
+	// Temperature is sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random,
+	// while lower values like 0.2 will make it more focused and deterministic
+	Temperature float32 `json:"temperature,omitempty"`
+	// TopP is an alternative to sampling with temperature, called nucleus sampling, where the model considers the results of
+	// the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.
+	TopP float32 `json:"top_p,omitempty"`
+	// N is number of responses to generate
+	N int `json:"n,omitempty"`
+	// Stream is whether to stream responses back as they are generated
+	Stream bool `json:"stream,omitempty"`
+	// Stop is up to 4 sequences where the API will stop generating further tokens.
+	Stop []string `json:"stop,omitempty"`
+	// MaxTokens is the maximum number of tokens to r eturn.
+	MaxTokens int `json:"max_tokens,omitempty"`
+	// PresencePenalty (-2, 2) penalize tokens that haven't appeared yet in the history.
+	PresencePenalty float32 `json:"presence_penalty,omitempty"`
+	// FrequencyPenalty (-2, 2) penalize tokens that appear too frequently in the history.
+	FrequencyPenalty float32 `json:"frequency_penalty,omitempty"`
+	// LogitBias modify the probability of specific tokens appearing in the completion.
+	LogitBias map[string]float32 `json:"logit_bias,omitempty"`
+	// User can be used to identify an end-user
+	User string `json:"user,omitempty"`
+}
+
+// CompletionRequest is a request for the completions API
+type CompletionRequest struct {
+	Model string `json:"model"`
+	// Prompt sets a list of string prompts to use.
+	Prompt []string `json:"prompt,omitempty"`
+	// Suffix comes after a completion of inserted text.
+	Suffix string `json:"suffix,omitempty"`
+	// MaxTokens sets how many tokens to complete up to. Max of 512
+	MaxTokens int `json:"max_tokens,omitempty"`
+	// Temperature sets sampling temperature to use
+	Temperature float32 `json:"temperature,omitempty"`
+	// TopP sets alternative to temperature for nucleus sampling
+	TopP *float32 `json:"top_p,omitempty"`
+	// N sets how many choice to create for each prompt
+	N *int `json:"n"`
+	// Stream sets whether to stream back results or not. Don't set this value in the request yourself
+	// as it will be overridden depending on if you use CompletionStream or Completion methods.
+	Stream bool `json:"stream,omitempty"`
+	// LogProbs sets include the probabilities of most likely tokens
+	LogProbs *int `json:"logprobs"`
+	// Echo sets back the prompt in addition to the completion
+	Echo bool `json:"echo"`
+	// Stop sets up to 4 sequences where the API will stop generating tokens. Response will not contain the stop sequence.
+	Stop []string `json:"stop,omitempty"`
+	// PresencePenalty sets number between 0 and 1 that penalizes tokens that have already appeared in the text so far.
+	PresencePenalty float32 `json:"presence_penalty"`
+	// FrequencyPenalty number between 0 and 1 that penalizes tokens on existing frequency in the text so far.
+	FrequencyPenalty float32 `json:"frequency_penalty"`
+	// BestOf sets how many of the n best completions to return. Defaults to 1.
+	BestOf int `json:"best_of,omitempty"`
+	// LogitBias sets modify the probability of specific tokens appearing in the completion.
+	LogitBias map[string]float32 `json:"logit_bias,omitempty"`
+	// User sets an end-user identifier. Can be used to associate completions generated by a specific user.
+	User string `json:"user,omitempty"`
+}
+
+// EditsRequest is a request for the edits API
+type EditsRequest struct {
+	// Model is ID of the model to use. You can use the List models API to see all of your available models,
+	// or see our Model overview for descriptions of them.
+	Model string `json:"model"`
+	// Input is the input text to use as a starting point for the edit.
+	Input string `json:"input,omitempty"`
+	// Instruction is the instruction that tells the model how to edit the prompt.
+	Instruction string `json:"instruction"`
+	// N is how many edits to generate for the input and instruction. Defaults to 1
+	N *int `json:"n,omitempty"`
+	// Temperature is sampling temperature to use
+	Temperature *float32 `json:"temperature,omitempty"`
+	// TopP is alternative to temperature for nucleus sampling
+	TopP *float32 `json:"top_p,omitempty"`
+}
+
+// EmbeddingsRequest is a request for the Embeddings API
+type EmbeddingsRequest struct {
+	// Input text to get embeddings for, encoded as a string or array of tokens. To get embeddings
+	// for multiple inputs in a single request, pass an array of strings or array of token arrays.
+	// Each input must not exceed 2048 tokens in length.
+	Input []string `json:"input"`
+	// Model is ID of the model to use
+	Model string `json:"model"`
+	// User is the request user is an optional parameter meant to be used to trace abusive requests
+	// back to the originating user. OpenAI states:
+	// "The [user] IDs should be a string that uniquely identifies each user. We recommend hashing
+	// their username or email address, in order to avoid sending us any identifying information.
+	// If you offer a preview of your product to non-logged in users, you can send a session ID
+	// instead."
+	User string `json:"user,omitempty"`
+}
+
+// LogProbResult represents logprob result of Choice
+type LogProbResult struct {
+	Tokens        []string             `json:"tokens"`
+	TokenLogProbs []float32            `json:"token_logprobs"`
+	TopLogProbs   []map[string]float32 `json:"top_logprobs"`
+	TextOffset    []int                `json:"text_offset"`
+}
+
+// ChatCompletionResponseMessage is a message returned in the response to the Chat Completions API
+type ChatCompletionResponseMessage struct {
+	Role    string `json:"role"`
+	Content string `json:"content"`
+}
+
+// ChatCompletionResponseChoice is one of the choices returned in the response to the Chat Completions API
+type ChatCompletionResponseChoice struct {
+	Index        int                           `json:"index"`
+	FinishReason string                        `json:"finish_reason"`
+	Message      ChatCompletionResponseMessage `json:"message"`
+}
+
+// ChatCompletionStreamResponseChoice is one of the choices returned in the response to the Chat Completions API
+type ChatCompletionStreamResponseChoice struct {
+	Index        int                           `json:"index"`
+	FinishReason string                        `json:"finish_reason"`
+	Delta        ChatCompletionResponseMessage `json:"delta"`
+}
+
+// ChatCompletionsResponseUsage is the object that returns how many tokens the completion's request used
+type ChatCompletionsResponseUsage struct {
+	PromptTokens     int `json:"prompt_tokens"`
+	CompletionTokens int `json:"completion_tokens"`
+	TotalTokens      int `json:"total_tokens"`
+}
+
+// ChatCompletionResponse is the full response from a request to the Chat Completions API
+type ChatCompletionResponse struct {
+	ID      string                         `json:"id"`
+	Object  string                         `json:"object"`
+	Created int                            `json:"created"`
+	Model   string                         `json:"model"`
+	Choices []ChatCompletionResponseChoice `json:"choices"`
+	Usage   ChatCompletionsResponseUsage   `json:"usage"`
+}
+
+type ChatCompletionStreamResponse struct {
+	ID      string                               `json:"id"`
+	Object  string                               `json:"object"`
+	Created int                                  `json:"created"`
+	Model   string                               `json:"model"`
+	Choices []ChatCompletionStreamResponseChoice `json:"choices"`
+	Usage   ChatCompletionsResponseUsage         `json:"usage"`
+}
+
+// CompletionResponseChoice is one of the choices returned in the response to the Completions API
+type CompletionResponseChoice struct {
+	Text         string        `json:"text"`
+	Index        int           `json:"index"`
+	LogProbs     LogProbResult `json:"logprobs"`
+	FinishReason string        `json:"finish_reason"`
+}
+
+// CompletionResponse is the full response from a request to the completions API
+type CompletionResponse struct {
+	ID      string                     `json:"id"`
+	Object  string                     `json:"object"`
+	Created int                        `json:"created"`
+	Model   string                     `json:"model"`
+	Choices []CompletionResponseChoice `json:"choices"`
+	Usage   CompletionResponseUsage    `json:"usage"`
+}
+
+// CompletionResponseUsage is the object that returns how many tokens the completion's request used
+type CompletionResponseUsage struct {
+	PromptTokens     int `json:"prompt_tokens"`
+	CompletionTokens int `json:"completion_tokens"`
+	TotalTokens      int `json:"total_tokens"`
+}
+
+// EditsResponse is the full response from a request to the edits API
+type EditsResponse struct {
+	Object  string                `json:"object"`
+	Created int                   `json:"created"`
+	Choices []EditsResponseChoice `json:"choices"`
+	Usage   EditsResponseUsage    `json:"usage"`
+}
+
+// EmbeddingsResult The inner result of a create embeddings request, containing the embeddings for a single input.
+type EmbeddingsResult struct {
+	// The type of object returned (e.g., "list", "object")
+	Object string `json:"object"`
+	// The embedding data for the input
+	Embedding []float64 `json:"embedding"`
+	Index     int       `json:"index"`
+}
+
+// EmbeddingsUsage The usage stats for an embeddings response
+type EmbeddingsUsage struct {
+	// The number of tokens used by the prompt
+	PromptTokens int `json:"prompt_tokens"`
+	// The total tokens used
+	TotalTokens int `json:"total_tokens"`
+}
+
+// EmbeddingsResponse is the response from a create embeddings request.
+// See: https://beta.openai.com/docs/api-reference/embeddings/create
+type EmbeddingsResponse struct {
+	Object string             `json:"object"`
+	Data   []EmbeddingsResult `json:"data"`
+	Usage  EmbeddingsUsage    `json:"usage"`
+}
+
+// EditsResponseChoice is one of the choices returned in the response to the Edits API
+type EditsResponseChoice struct {
+	Text  string `json:"text"`
+	Index int    `json:"index"`
+}
+
+// EditsResponseUsage is a structure used in the response from a request to the edits API
+type EditsResponseUsage struct {
+	PromptTokens     int `json:"prompt_tokens"`
+	CompletionTokens int `json:"completion_tokens"`
+	TotalTokens      int `json:"total_tokens"`
+}
+
+// SearchRequest is a request for the document search API
+type SearchRequest struct {
+	Documents []string `json:"documents"`
+	Query     string   `json:"query"`
+}
+
+// SearchData is a single search result from the document search API
+type SearchData struct {
+	Document int     `json:"document"`
+	Object   string  `json:"object"`
+	Score    float64 `json:"score"`
+}
+
+// SearchResponse is the full response from a request to the document search API
+type SearchResponse struct {
+	Data   []SearchData `json:"data"`
+	Object string       `json:"object"`
+}
+
+// ImageRequest represents the request structure for the image API.
+type ImageRequest struct {
+	Prompt         string `json:"prompt,omitempty"`
+	N              int    `json:"n,omitempty"`
+	Size           string `json:"size,omitempty"`
+	ResponseFormat string `json:"response_format,omitempty"`
+	User           string `json:"user,omitempty"`
+}
+
+// ImageResponse represents a response structure for image API.
+type ImageResponse struct {
+	Created int64                    `json:"created,omitempty"`
+	Data    []ImageResponseDataInner `json:"data,omitempty"`
+}
+
+// ImageResponseDataInner represents a response data structure for image API.
+type ImageResponseDataInner struct {
+	URL     string `json:"url,omitempty"`
+	B64JSON string `json:"b64_json,omitempty"`
+}

+ 69 - 0
gpt/options.go

@@ -0,0 +1,69 @@
+package gpt
+
+import (
+	"net/http"
+	"time"
+)
+
+// Option sets gpt-3 Client option values.
+type Option interface {
+	apply(client) error
+}
+
+// ClientOption are options that can be passed when creating a new client
+type ClientOption func(*client) *client
+
+func (fn ClientOption) apply(cli *client) *client {
+	return fn(cli)
+}
+
+// WithOrg is a client option that allows you to override the organization ID
+func WithOrg(id string) ClientOption {
+	return func(cli *client) *client {
+		cli.idOrg = id
+		return cli
+	}
+}
+
+// WithDefaultEngine is a client option that allows you to override the default engine of the client
+func WithDefaultEngine(engine string) ClientOption {
+	return func(cli *client) *client {
+		cli.defaultEngine = engine
+		return cli
+	}
+}
+
+// WithUserAgent is a client option that allows you to override the default user agent of the client
+func WithUserAgent(userAgent string) ClientOption {
+	return func(cli *client) *client {
+		cli.userAgent = userAgent
+		return cli
+	}
+}
+
+// WithBaseURL is a client option that allows you to override the default base url of the client.
+// The default base url is "https://api.openai.com/v1"
+func WithBaseURL(baseURL string) ClientOption {
+	return func(cli *client) *client {
+		cli.baseURL = baseURL
+		return cli
+	}
+}
+
+// WithHTTPClient allows you to override the internal http.Client used
+func WithHTTPClient(httpClient *http.Client) ClientOption {
+	return func(cli *client) *client {
+		cli.httpClient = httpClient
+		return cli
+	}
+}
+
+// WithTimeout is a client option that allows you to override the default timeout duration of requests
+// for the client. The default is 30 seconds. If you are overriding the http client as well, just include
+// the timeout there.
+func WithTimeout(timeout time.Duration) ClientOption {
+	return func(cli *client) *client {
+		cli.httpClient.Timeout = timeout
+		return cli
+	}
+}

+ 11 - 0
gpt/utils.go

@@ -0,0 +1,11 @@
+package gpt
+
+// IntPtr converts an integer to an *int as a convenience
+func IntPtr(i int) *int {
+	return &i
+}
+
+// Float32Ptr converts a float32 to a *float32 as a convenience
+func Float32Ptr(f float32) *float32 {
+	return &f
+}

+ 4 - 0
hack/config.yaml

@@ -0,0 +1,4 @@
+
+# CLI tool, only in development environment.
+# https://goframe.org/pages/viewpage.action?pageId=3673173
+gfcli:

+ 48 - 0
internal/cmd/cmd.go

@@ -0,0 +1,48 @@
+package cmd
+
+import (
+	"context"
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/net/ghttp"
+	"github.com/gogf/gf/v2/net/goai"
+	"github.com/gogf/gf/v2/os/gcmd"
+	"go-gpt/internal/consts"
+	"go-gpt/internal/controller"
+)
+
+var (
+	Main = gcmd.Command{
+		Name:  "main",
+		Usage: "main",
+		Brief: "start http server",
+		Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
+			s := g.Server()
+
+			s.Group("/", func(group *ghttp.RouterGroup) {
+				group.Bind(controller.Hello)
+				//router.BindController(group)
+			})
+
+			enhanceOpenAPIDoc(s)
+
+			s.Run()
+			return nil
+		},
+	}
+)
+
+func enhanceOpenAPIDoc(s *ghttp.Server) {
+	openapi := s.GetOpenApi()
+	openapi.Config.CommonResponse = ghttp.DefaultHandlerResponse{}
+	openapi.Config.CommonResponseDataField = `Data`
+
+	// API description.
+	openapi.Info = goai.Info{
+		Title:       consts.OpenAPITitle,
+		Description: consts.OpenAPIDescription,
+		Contact: &goai.Contact{
+			Name: "GoFrame",
+			URL:  "https://goframe.org",
+		},
+	}
+}

+ 1 - 0
internal/consts/consts.go

@@ -0,0 +1 @@
+package consts

+ 6 - 0
internal/consts/consts_openapi.go

@@ -0,0 +1,6 @@
+package consts
+
+const (
+	OpenAPITitle       = `gpt dome`
+	OpenAPIDescription = `This is a simple demos HTTP server project that is using GoFrame. Enjoy 💖 `
+)

+ 65 - 0
internal/controller/hello.go

@@ -0,0 +1,65 @@
+package controller
+
+import (
+	"context"
+	"encoding/json"
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/os/glog"
+	"go-gpt/gpt"
+
+	"go-gpt/api/v1"
+)
+
+var (
+	Hello = cHello{}
+)
+
+type Message struct {
+	Content string `json:"content"`
+}
+type cHello struct{}
+
+func (c *cHello) Hello(ctx context.Context, req *v1.HelloReq) (res *v1.HelloRes, err error) {
+	re := g.RequestFromCtx(ctx)
+	//g.RequestFromCtx(ctx).Response.Add("Content-Type", "application/json")
+	//g.RequestFromCtx(ctx).Header.Add("Transfer-Encoding", "chunked")
+	re.Response.Header().Set("Transfer-Encoding", "chunked")
+	re.Response.Header().Set("Content-Type", "application/json")
+	w := re.Response.Writer
+	encoder := json.NewEncoder(w)
+
+	// 初始化client
+	client := gpt.NewClient("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")
+	err = client.ChatCompletionStream(ctx, &gpt.ChatCompletionRequest{
+		Model: gpt.GPT3Dot5Turbo,
+		Messages: []gpt.ChatCompletionRequestMessage{
+			{
+				Role:    "user",
+				Content: "编写一个c++冒泡算法",
+			},
+		},
+		MaxTokens:   50,
+		Temperature: 0,
+	}, func(response *gpt.ChatCompletionStreamResponse) {
+
+		// 检查Choices字段是否存在
+		if len(response.Choices) > 0 {
+			// 提取Content字段
+			content := response.Choices[0].Delta.Content
+			// 将Content字段作为一个JSON对象发送给客户端
+			message := Message{Content: content}
+			if err := encoder.Encode(message); err != nil {
+				return
+			}
+			re.Response.WriteHeader(200)
+			w.Flush()
+		}
+	})
+
+	if err != nil {
+		glog.Debug(ctx, err)
+		return
+	}
+
+	return
+}

+ 0 - 0
internal/dao/.gitkeep


+ 0 - 0
internal/logic/.gitkeep


+ 0 - 0
internal/model/.gitkeep


+ 0 - 0
internal/model/do/.gitkeep


+ 0 - 0
internal/model/entity/.gitkeep


+ 1 - 0
internal/packed/packed.go

@@ -0,0 +1 @@
+package packed

+ 0 - 0
internal/service/.gitkeep


+ 13 - 0
main.go

@@ -0,0 +1,13 @@
+package main
+
+import (
+	_ "go-gpt/internal/packed"
+
+	"github.com/gogf/gf/v2/os/gctx"
+
+	"go-gpt/internal/cmd"
+)
+
+func main() {
+	cmd.Main.Run(gctx.New())
+}

+ 84 - 0
manifest/config/config.yaml

@@ -0,0 +1,84 @@
+server:
+  address: ":8080"
+  serverRoot: "resource/public"
+  dumpRouterMap: true
+  routeOverWrite: true
+  openapiPath: "/api.json"
+  swaggerPath: "/swagger"
+  NameToUriType: 3
+  maxHeaderBytes: "20KB"
+  clientMaxBodySize: "50MB"
+  # Logging配置
+  logPath: "resource/log/server" # 日志文件存储目录路径,建议使用绝对路径。默认为空,表示关闭
+  logStdout: true # 日志是否输出到终端。默认为true
+  errorStack: false # 当Server捕获到异常时是否记录堆栈信息到日志中。默认为true
+  errorLogEnabled: true # 是否记录异常日志信息到日志中。默认为true
+  errorLogPattern: "error-{Ymd}.log" # 异常错误日志文件格式。默认为"error-{Ymd}.log"
+  accessLogEnabled: true # 是否记录访问日志。默认为false
+  accessLogPattern: "access-{Ymd}.log" # 访问日志文件格式。默认为"access-{Ymd}.log"
+
+logger:
+  path: "resource/log/run"
+  file: "{Y-m-d}.log"
+  level: "all"
+  stdout: true
+
+# Database.
+database:
+  logger:
+    level: "all"
+    stdout: true
+    Path: "resource/log/sql"
+
+  default:
+    link: "mysql:nodemonitor:m4A6zLaDnRCNd4xw@tcp(156.234.193.212:33060)/nodemonitor?loc=Local&parseTime=true" #156.234.193.212
+    #link: "mysql:root:123456@tcp(127.0.0.1:3306)/nodeMonitor?loc=Local&parseTime=true"
+    debug: true
+    charset: "utf8mb4" #数据库编码
+    dryRun: false #空跑
+    maxIdle: 10 #连接池最大闲置的连接数
+    maxOpen: 30 #连接池最大打开的连接数
+    maxLifetime: 30 #(单位秒)连接对象可重复使用的时间长度
+
+node:
+  startTime: 15 #用于查询15分钟内的数据 单位分钟
+  taskName: "ping_task" #任务名称
+  taskStatusName: "ping_status_task" #任务名称
+  nodePing: 2 #用于表示是不是检测PING的节点
+  taskStatusTime: 30 #单位分钟
+  rootUsername: "admin"
+  rootPassword: "qoqoiwooqp@#"
+  clearLogTime: 10  #清理10天前的数据
+
+gfToken:
+  cacheKey: "gfToken_"
+  timeOut: 10800
+  maxRefresh: 5400
+  multiLogin: true
+  encryptKey: "49c54195e750b04e74a8429b17896586"
+  cacheModel: "redis"
+  excludePaths:
+    - "/api/v1/auth/login"
+    - "/api/v1/auth/loginout"
+    - "/api/v1/node/add"
+
+# Redis 配置示例
+redis:
+  # 单实例配置
+  default:
+    address: 127.0.0.1:6379
+    db: 1
+    idleTimeout: 600
+    maxActive: 100
+
+#system:
+#  notCheckAuthAdminIds: [1, 2, 31] #无需验证后台权限的用户id
+#  dataDir: "./resource/data"
+#  cache:
+#    model: "redis" #缓存模式 memory OR redis
+#    prefix: "liarCache_" #缓存前缀
+
+##casbin配置
+#casbin:
+#  modelFile: "./resource/casbin/rbac_model.conf"
+#  policyFile: "./resource/casbin/rbac_policy.csv"

+ 21 - 0
manifest/deploy/kustomize/base/deployment.yaml

@@ -0,0 +1,21 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: template-single
+  labels:
+    app: template-single
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: template-single
+  template:
+    metadata:
+      labels:
+        app: template-single
+    spec:
+      containers:
+        - name : main
+          image: template-single
+          imagePullPolicy: Always
+

+ 8 - 0
manifest/deploy/kustomize/base/kustomization.yaml

@@ -0,0 +1,8 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+- deployment.yaml
+- service.yaml
+
+
+

+ 12 - 0
manifest/deploy/kustomize/base/service.yaml

@@ -0,0 +1,12 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: template-single
+spec:
+  ports:
+  - port: 80
+    protocol: TCP
+    targetPort: 8000
+  selector:
+    app: template-single
+

+ 14 - 0
manifest/deploy/kustomize/overlays/develop/configmap.yaml

@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: template-single-configmap
+data:
+  config.yaml: |
+    server:
+      address:     ":8000"
+      openapiPath: "/api.json"
+      swaggerPath: "/swagger"
+
+    logger:
+      level : "all"
+      stdout: true

+ 10 - 0
manifest/deploy/kustomize/overlays/develop/deployment.yaml

@@ -0,0 +1,10 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: template-single
+spec:
+  template:
+    spec:
+      containers:
+        - name : main
+          image: template-single:develop

+ 14 - 0
manifest/deploy/kustomize/overlays/develop/kustomization.yaml

@@ -0,0 +1,14 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+
+resources:
+- ../../base
+- configmap.yaml
+
+patchesStrategicMerge:
+- deployment.yaml
+
+namespace: default
+
+
+

+ 16 - 0
manifest/docker/Dockerfile

@@ -0,0 +1,16 @@
+FROM loads/alpine:3.8
+
+###############################################################################
+#                                INSTALLATION
+###############################################################################
+
+ENV WORKDIR                 /app
+ADD resource                $WORKDIR/
+ADD ./temp/linux_amd64/main $WORKDIR/main
+RUN chmod +x $WORKDIR/main
+
+###############################################################################
+#                                   START
+###############################################################################
+WORKDIR $WORKDIR
+CMD ./main

+ 8 - 0
manifest/docker/docker.sh

@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# This shell is executed before docker build.
+
+
+
+
+

+ 0 - 0
resource/i18n/.gitkeep


+ 345 - 0
resource/log/server/2023-03-30.log

@@ -0,0 +1,345 @@
+2023-03-30 16:08:07.159 [INFO] swagger ui is serving at address: http://127.0.0.1:8080/swagger/
+2023-03-30 16:08:07.159 [INFO] pid[24566]: http server started listening on [:8080]
+2023-03-30 16:08:07.160 [INFO] openapi specification is serving at address: http://127.0.0.1:8080/api.json
+
+  ADDRESS | METHOD |   ROUTE    |                             HANDLER                             |           MIDDLEWARE             
+----------|--------|------------|-----------------------------------------------------------------|----------------------------------
+  :8080   | ALL    | /*         | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE                
+----------|--------|------------|-----------------------------------------------------------------|----------------------------------
+  :8080   | ALL    | /api.json  | github.com/gogf/gf/v2/net/ghttp.(*Server).openapiSpec           |                                  
+----------|--------|------------|-----------------------------------------------------------------|----------------------------------
+  :8080   | POST   | /hello     | go-gpt/internal/controller.(*cHello).Hello                      | ghttp.MiddlewareHandlerResponse  
+----------|--------|------------|-----------------------------------------------------------------|----------------------------------
+  :8080   | ALL    | /swagger/* | github.com/gogf/gf/v2/net/ghttp.(*Server).swaggerUI             | HOOK_BEFORE_SERVE                
+----------|--------|------------|-----------------------------------------------------------------|----------------------------------
+
+2023-03-30 16:11:54.790 [INFO] pid[24566]: all servers shutdown
+2023-03-30 16:11:56.888 [INFO] swagger ui is serving at address: http://127.0.0.1:8080/swagger/
+2023-03-30 16:11:56.888 [INFO] openapi specification is serving at address: http://127.0.0.1:8080/api.json
+2023-03-30 16:11:56.888 [INFO] pid[24815]: http server started listening on [:8080]
+
+  ADDRESS | METHOD |       ROUTE        |                             HANDLER                             |           MIDDLEWARE             
+----------|--------|--------------------|-----------------------------------------------------------------|----------------------------------
+  :8080   | ALL    | /*                 | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE                
+----------|--------|--------------------|-----------------------------------------------------------------|----------------------------------
+  :8080   | ALL    | /api.json          | github.com/gogf/gf/v2/net/ghttp.(*Server).openapiSpec           |                                  
+----------|--------|--------------------|-----------------------------------------------------------------|----------------------------------
+  :8080   | POST   | /hello/hello/hello | go-gpt/internal/controller.(*cHello).Hello                      | ghttp.MiddlewareHandlerResponse  
+          |        |                    |                                                                 | router.MiddlewareCORS            
+----------|--------|--------------------|-----------------------------------------------------------------|----------------------------------
+  :8080   | ALL    | /swagger/*         | github.com/gogf/gf/v2/net/ghttp.(*Server).swaggerUI             | HOOK_BEFORE_SERVE                
+----------|--------|--------------------|-----------------------------------------------------------------|----------------------------------
+
+2023-03-30 16:12:38.262 [INFO] pid[24815]: all servers shutdown
+2023-03-30 16:12:40.330 [INFO] swagger ui is serving at address: http://127.0.0.1:8080/swagger/
+2023-03-30 16:12:40.330 [INFO] pid[24883]: http server started listening on [:8080]
+2023-03-30 16:12:40.330 [INFO] openapi specification is serving at address: http://127.0.0.1:8080/api.json
+
+  ADDRESS | METHOD |    ROUTE     |                             HANDLER                             |           MIDDLEWARE             
+----------|--------|--------------|-----------------------------------------------------------------|----------------------------------
+  :8080   | ALL    | /*           | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE                
+----------|--------|--------------|-----------------------------------------------------------------|----------------------------------
+  :8080   | ALL    | /api.json    | github.com/gogf/gf/v2/net/ghttp.(*Server).openapiSpec           |                                  
+----------|--------|--------------|-----------------------------------------------------------------|----------------------------------
+  :8080   | POST   | /hello/hello | go-gpt/internal/controller.(*cHello).Hello                      | ghttp.MiddlewareHandlerResponse  
+          |        |              |                                                                 | router.MiddlewareCORS            
+----------|--------|--------------|-----------------------------------------------------------------|----------------------------------
+  :8080   | ALL    | /swagger/*   | github.com/gogf/gf/v2/net/ghttp.(*Server).swaggerUI             | HOOK_BEFORE_SERVE                
+----------|--------|--------------|-----------------------------------------------------------------|----------------------------------
+
+2023-03-30 16:13:00.353 [INFO] pid[24883]: all servers shutdown
+2023-03-30 16:13:01.741 [INFO] swagger ui is serving at address: http://127.0.0.1:8080/swagger/
+2023-03-30 16:13:01.741 [INFO] pid[24936]: http server started listening on [:8080]
+2023-03-30 16:13:01.741 [INFO] openapi specification is serving at address: http://127.0.0.1:8080/api.json
+
+  ADDRESS | METHOD |   ROUTE    |                             HANDLER                             |           MIDDLEWARE             
+----------|--------|------------|-----------------------------------------------------------------|----------------------------------
+  :8080   | ALL    | /*         | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE                
+----------|--------|------------|-----------------------------------------------------------------|----------------------------------
+  :8080   | ALL    | /api.json  | github.com/gogf/gf/v2/net/ghttp.(*Server).openapiSpec           |                                  
+----------|--------|------------|-----------------------------------------------------------------|----------------------------------
+  :8080   | POST   | /hello     | go-gpt/internal/controller.(*cHello).Hello                      | ghttp.MiddlewareHandlerResponse  
+          |        |            |                                                                 | router.MiddlewareCORS            
+----------|--------|------------|-----------------------------------------------------------------|----------------------------------
+  :8080   | ALL    | /swagger/* | github.com/gogf/gf/v2/net/ghttp.(*Server).swaggerUI             | HOOK_BEFORE_SERVE                
+----------|--------|------------|-----------------------------------------------------------------|----------------------------------
+
+2023-03-30 16:13:20.289 [ERRO] http: superfluous response.WriteHeader call from github.com/gogf/gf/v2/net/ghttp.(*ResponseWriter).Flush (ghttp_response_writer.go:61)
+Stack:
+1.  github.com/gogf/gf/v2/net/ghttp.(*ResponseWriter).Flush
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_response_writer.go:61
+2.  github.com/gogf/gf/v2/net/ghttp.(*Response).Flush
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_response.go:165
+3.  github.com/gogf/gf/v2/net/ghttp.(*Server).ServeHTTP
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_server_handler.go:196
+
+2023-03-30 16:16:09.608 [INFO] pid[24936]: all servers shutdown
+2023-03-30 16:16:11.628 [INFO] swagger ui is serving at address: http://127.0.0.1:8080/swagger/
+2023-03-30 16:16:11.628 [INFO] pid[25141]: http server started listening on [:8080]
+2023-03-30 16:16:11.628 [INFO] openapi specification is serving at address: http://127.0.0.1:8080/api.json
+
+  ADDRESS | METHOD |   ROUTE    |                             HANDLER                             |    MIDDLEWARE      
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /*         | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE  
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /api.json  | github.com/gogf/gf/v2/net/ghttp.(*Server).openapiSpec           |                    
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | POST   | /hello     | go-gpt/internal/controller.(*cHello).Hello                      |                    
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /swagger/* | github.com/gogf/gf/v2/net/ghttp.(*Server).swaggerUI             | HOOK_BEFORE_SERVE  
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+
+2023-03-30 16:16:21.948 [ERRO] http: superfluous response.WriteHeader call from github.com/gogf/gf/v2/net/ghttp.(*ResponseWriter).Flush (ghttp_response_writer.go:61)
+Stack:
+1.  github.com/gogf/gf/v2/net/ghttp.(*ResponseWriter).Flush
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_response_writer.go:61
+2.  github.com/gogf/gf/v2/net/ghttp.(*Response).Flush
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_response.go:165
+3.  github.com/gogf/gf/v2/net/ghttp.(*Server).ServeHTTP
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_server_handler.go:196
+
+2023-03-30 16:18:25.062 [INFO] pid[25141]: all servers shutdown
+2023-03-30 16:18:27.174 [INFO] swagger ui is serving at address: http://127.0.0.1:8080/swagger/
+2023-03-30 16:18:27.174 [INFO] openapi specification is serving at address: http://127.0.0.1:8080/api.json
+2023-03-30 16:18:27.174 [INFO] pid[25317]: http server started listening on [:8080]
+
+  ADDRESS | METHOD |   ROUTE    |                             HANDLER                             |    MIDDLEWARE      
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /*         | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE  
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /api.json  | github.com/gogf/gf/v2/net/ghttp.(*Server).openapiSpec           |                    
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | POST   | /hello     | go-gpt/internal/controller.(*cHello).Hello                      |                    
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /swagger/* | github.com/gogf/gf/v2/net/ghttp.(*Server).swaggerUI             | HOOK_BEFORE_SERVE  
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+
+2023-03-30 16:18:48.924 [ERRO] http: superfluous response.WriteHeader call from github.com/gogf/gf/v2/net/ghttp.(*ResponseWriter).Flush (ghttp_response_writer.go:61)
+Stack:
+1.  github.com/gogf/gf/v2/net/ghttp.(*ResponseWriter).Flush
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_response_writer.go:61
+2.  github.com/gogf/gf/v2/net/ghttp.(*Response).Flush
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_response.go:165
+3.  github.com/gogf/gf/v2/net/ghttp.(*Server).ServeHTTP
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_server_handler.go:196
+
+2023-03-30 16:21:05.124 [INFO] pid[25317]: all servers shutdown
+2023-03-30 16:21:07.182 [INFO] swagger ui is serving at address: http://127.0.0.1:8080/swagger/
+2023-03-30 16:21:07.181 [INFO] pid[25505]: http server started listening on [:8080]
+2023-03-30 16:21:07.182 [INFO] openapi specification is serving at address: http://127.0.0.1:8080/api.json
+
+  ADDRESS | METHOD |   ROUTE    |                             HANDLER                             |    MIDDLEWARE      
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /*         | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE  
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /api.json  | github.com/gogf/gf/v2/net/ghttp.(*Server).openapiSpec           |                    
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | POST   | /hello     | go-gpt/internal/controller.(*cHello).Hello                      |                    
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /swagger/* | github.com/gogf/gf/v2/net/ghttp.(*Server).swaggerUI             | HOOK_BEFORE_SERVE  
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+
+2023-03-30 16:21:13.637 [ERRO] http: superfluous response.WriteHeader call from github.com/gogf/gf/v2/net/ghttp.(*ResponseWriter).Flush (ghttp_response_writer.go:61)
+Stack:
+1.  github.com/gogf/gf/v2/net/ghttp.(*ResponseWriter).Flush
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_response_writer.go:61
+2.  github.com/gogf/gf/v2/net/ghttp.(*Response).Flush
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_response.go:165
+3.  github.com/gogf/gf/v2/net/ghttp.(*Server).ServeHTTP
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_server_handler.go:196
+
+2023-03-30 16:22:42.330 [INFO] pid[25505]: all servers shutdown
+2023-03-30 16:22:44.354 [INFO] swagger ui is serving at address: http://127.0.0.1:8080/swagger/
+2023-03-30 16:22:44.354 [INFO] pid[25645]: http server started listening on [:8080]
+2023-03-30 16:22:44.355 [INFO] openapi specification is serving at address: http://127.0.0.1:8080/api.json
+
+  ADDRESS | METHOD |   ROUTE    |                             HANDLER                             |    MIDDLEWARE      
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /*         | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE  
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /api.json  | github.com/gogf/gf/v2/net/ghttp.(*Server).openapiSpec           |                    
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | POST   | /hello     | go-gpt/internal/controller.(*cHello).Hello                      |                    
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /swagger/* | github.com/gogf/gf/v2/net/ghttp.(*Server).swaggerUI             | HOOK_BEFORE_SERVE  
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+
+2023-03-30 16:22:50.978 [ERRO] http: superfluous response.WriteHeader call from github.com/gogf/gf/v2/net/ghttp.(*ResponseWriter).Flush (ghttp_response_writer.go:61)
+Stack:
+1.  github.com/gogf/gf/v2/net/ghttp.(*ResponseWriter).Flush
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_response_writer.go:61
+2.  github.com/gogf/gf/v2/net/ghttp.(*Response).Flush
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_response.go:165
+3.  github.com/gogf/gf/v2/net/ghttp.(*Server).ServeHTTP
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_server_handler.go:196
+
+2023-03-30 16:26:14.128 [INFO] pid[25645]: all servers shutdown
+2023-03-30 16:26:16.087 [INFO] swagger ui is serving at address: http://127.0.0.1:8080/swagger/
+2023-03-30 16:26:16.087 [INFO] openapi specification is serving at address: http://127.0.0.1:8080/api.json
+2023-03-30 16:26:16.087 [INFO] pid[25879]: http server started listening on [:8080]
+
+  ADDRESS | METHOD |   ROUTE    |                             HANDLER                             |    MIDDLEWARE      
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /*         | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE  
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /api.json  | github.com/gogf/gf/v2/net/ghttp.(*Server).openapiSpec           |                    
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | POST   | /hello     | go-gpt/internal/controller.(*cHello).Hello                      |                    
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /swagger/* | github.com/gogf/gf/v2/net/ghttp.(*Server).swaggerUI             | HOOK_BEFORE_SERVE  
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+
+2023-03-30 16:26:29.216 [ERRO] http: superfluous response.WriteHeader call from github.com/gogf/gf/v2/net/ghttp.(*ResponseWriter).Flush (ghttp_response_writer.go:61)
+Stack:
+1.  github.com/gogf/gf/v2/net/ghttp.(*ResponseWriter).Flush
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_response_writer.go:61
+2.  github.com/gogf/gf/v2/net/ghttp.(*Response).Flush
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_response.go:165
+3.  github.com/gogf/gf/v2/net/ghttp.(*Server).ServeHTTP
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_server_handler.go:196
+
+2023-03-30 16:26:58.535 [INFO] pid[25879]: all servers shutdown
+2023-03-30 16:27:00.565 [INFO] swagger ui is serving at address: http://127.0.0.1:8080/swagger/
+2023-03-30 16:27:00.565 [INFO] pid[25950]: http server started listening on [:8080]
+2023-03-30 16:27:00.565 [INFO] openapi specification is serving at address: http://127.0.0.1:8080/api.json
+
+  ADDRESS | METHOD |   ROUTE    |                             HANDLER                             |    MIDDLEWARE      
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /*         | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE  
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /api.json  | github.com/gogf/gf/v2/net/ghttp.(*Server).openapiSpec           |                    
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | POST   | /hello     | go-gpt/internal/controller.(*cHello).Hello                      |                    
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /swagger/* | github.com/gogf/gf/v2/net/ghttp.(*Server).swaggerUI             | HOOK_BEFORE_SERVE  
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+
+2023-03-30 16:27:04.141 [ERRO] http: superfluous response.WriteHeader call from github.com/gogf/gf/v2/net/ghttp.(*ResponseWriter).Flush (ghttp_response_writer.go:61)
+Stack:
+1.  github.com/gogf/gf/v2/net/ghttp.(*ResponseWriter).Flush
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_response_writer.go:61
+2.  go-gpt/internal/controller.(*cHello).Hello.func1
+    /Users/cauto/Desktop/work/go_work/go-gpt/internal/controller/hello.go:53
+3.  go-gpt/gpt.(*client).ChatCompletionStream
+    /Users/cauto/Desktop/work/go_work/go-gpt/gpt/gpt.go:240
+4.  go-gpt/internal/controller.(*cHello).Hello
+    /Users/cauto/Desktop/work/go_work/go-gpt/internal/controller/hello.go:31
+5.  github.com/gogf/gf/v2/net/ghttp.(*middleware).callHandlerFunc.func1
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_request_middleware.go:152
+6.  github.com/gogf/gf/v2/net/ghttp.niceCallFunc
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_func.go:55
+7.  github.com/gogf/gf/v2/net/ghttp.(*middleware).callHandlerFunc
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_request_middleware.go:129
+8.  github.com/gogf/gf/v2/net/ghttp.(*middleware).Next.func1
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_request_middleware.go:75
+9.  github.com/gogf/gf/v2/util/gutil.TryCatch
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/util/gutil/gutil.go:56
+10. github.com/gogf/gf/v2/net/ghttp.(*middleware).Next
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_request_middleware.go:49
+11. github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_middleware_tracing.go:78
+12. github.com/gogf/gf/v2/net/ghttp.(*middleware).Next.func1.5
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_request_middleware.go:96
+13. github.com/gogf/gf/v2/net/ghttp.niceCallFunc
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_func.go:55
+14. github.com/gogf/gf/v2/net/ghttp.(*middleware).Next.func1
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_request_middleware.go:95
+15. github.com/gogf/gf/v2/util/gutil.TryCatch
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/util/gutil/gutil.go:56
+16. github.com/gogf/gf/v2/net/ghttp.(*middleware).Next
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_request_middleware.go:49
+17. github.com/gogf/gf/v2/net/ghttp.(*Server).ServeHTTP
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_server_handler.go:132
+
+2023-03-30 16:28:13.222 [INFO] pid[25950]: all servers shutdown
+2023-03-30 16:28:15.221 [INFO] swagger ui is serving at address: http://127.0.0.1:8080/swagger/
+2023-03-30 16:28:15.221 [INFO] pid[26049]: http server started listening on [:8080]
+2023-03-30 16:28:15.222 [INFO] openapi specification is serving at address: http://127.0.0.1:8080/api.json
+
+  ADDRESS | METHOD |   ROUTE    |                             HANDLER                             |    MIDDLEWARE      
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /*         | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE  
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /api.json  | github.com/gogf/gf/v2/net/ghttp.(*Server).openapiSpec           |                    
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | POST   | /hello     | go-gpt/internal/controller.(*cHello).Hello                      |                    
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /swagger/* | github.com/gogf/gf/v2/net/ghttp.(*Server).swaggerUI             | HOOK_BEFORE_SERVE  
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+
+2023-03-30 16:28:22.796 [ERRO] http: superfluous response.WriteHeader call from github.com/gogf/gf/v2/net/ghttp.(*ResponseWriter).Flush (ghttp_response_writer.go:61)
+Stack:
+1.  github.com/gogf/gf/v2/net/ghttp.(*ResponseWriter).Flush
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_response_writer.go:61
+2.  github.com/gogf/gf/v2/net/ghttp.(*Response).Flush
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_response.go:165
+3.  github.com/gogf/gf/v2/net/ghttp.(*Server).ServeHTTP
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_server_handler.go:196
+
+2023-03-30 16:35:57.712 [INFO] pid[26049]: all servers shutdown
+2023-03-30 16:36:04.824 [INFO] swagger ui is serving at address: http://127.0.0.1:8080/swagger/
+2023-03-30 16:36:04.824 [INFO] pid[26516]: http server started listening on [:8080]
+2023-03-30 16:36:04.824 [INFO] openapi specification is serving at address: http://127.0.0.1:8080/api.json
+
+  ADDRESS | METHOD |   ROUTE    |                             HANDLER                             |    MIDDLEWARE      
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /*         | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE  
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /api.json  | github.com/gogf/gf/v2/net/ghttp.(*Server).openapiSpec           |                    
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | POST   | /hello     | go-gpt/internal/controller.(*cHello).Hello                      |                    
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /swagger/* | github.com/gogf/gf/v2/net/ghttp.(*Server).swaggerUI             | HOOK_BEFORE_SERVE  
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+
+2023-03-30 16:36:12.439 [ERRO] http: superfluous response.WriteHeader call from github.com/gogf/gf/v2/net/ghttp.(*ResponseWriter).Flush (ghttp_response_writer.go:61)
+Stack:
+1.  github.com/gogf/gf/v2/net/ghttp.(*ResponseWriter).Flush
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_response_writer.go:61
+2.  github.com/gogf/gf/v2/net/ghttp.(*Response).Flush
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_response.go:165
+3.  github.com/gogf/gf/v2/net/ghttp.(*Server).ServeHTTP
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_server_handler.go:196
+
+2023-03-30 16:39:55.671 [INFO] pid[26516]: all servers shutdown
+2023-03-30 16:39:56.880 [INFO] swagger ui is serving at address: http://127.0.0.1:8080/swagger/
+2023-03-30 16:39:56.880 [INFO] openapi specification is serving at address: http://127.0.0.1:8080/api.json
+2023-03-30 16:39:56.880 [INFO] pid[26772]: http server started listening on [:8080]
+
+  ADDRESS | METHOD |   ROUTE    |                             HANDLER                             |    MIDDLEWARE      
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /*         | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE  
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /api.json  | github.com/gogf/gf/v2/net/ghttp.(*Server).openapiSpec           |                    
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | POST   | /hello     | go-gpt/internal/controller.(*cHello).Hello                      |                    
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /swagger/* | github.com/gogf/gf/v2/net/ghttp.(*Server).swaggerUI             | HOOK_BEFORE_SERVE  
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+
+2023-03-30 16:40:05.948 [ERRO] http: superfluous response.WriteHeader call from github.com/gogf/gf/v2/net/ghttp.(*ResponseWriter).Flush (ghttp_response_writer.go:61)
+Stack:
+1.  github.com/gogf/gf/v2/net/ghttp.(*ResponseWriter).Flush
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_response_writer.go:61
+2.  github.com/gogf/gf/v2/net/ghttp.(*Response).Flush
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_response.go:165
+3.  github.com/gogf/gf/v2/net/ghttp.(*Server).ServeHTTP
+    /Users/cauto/Desktop/work/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.1/net/ghttp/ghttp_server_handler.go:196
+
+2023-03-30 16:45:52.921 [INFO] pid[26772]: all servers shutdown
+2023-03-30 16:45:54.925 [INFO] swagger ui is serving at address: http://127.0.0.1:8080/swagger/
+2023-03-30 16:45:54.925 [INFO] pid[27169]: http server started listening on [:8080]
+2023-03-30 16:45:54.926 [INFO] openapi specification is serving at address: http://127.0.0.1:8080/api.json
+
+  ADDRESS | METHOD |   ROUTE    |                             HANDLER                             |    MIDDLEWARE      
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /*         | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE  
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /api.json  | github.com/gogf/gf/v2/net/ghttp.(*Server).openapiSpec           |                    
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | POST   | /hello     | go-gpt/internal/controller.(*cHello).Hello                      |                    
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+  :8080   | ALL    | /swagger/* | github.com/gogf/gf/v2/net/ghttp.(*Server).swaggerUI             | HOOK_BEFORE_SERVE  
+----------|--------|------------|-----------------------------------------------------------------|--------------------
+
+2023-03-30 16:50:41.718 [INFO] pid[27169]: all servers shutdown

+ 21 - 0
resource/log/server/access-20230330.log

@@ -0,0 +1,21 @@
+2023-03-30 16:08:14.866 {70260385fa23511792ae590c9cd8c58e} 200 "GET http 127.0.0.1:8080 /swagger HTTP/1.1" 0.000, 127.0.0.1, "", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.54"
+2023-03-30 16:08:14.984 {a809ff8bfa23511793ae590cba8e64ec} 200 "GET http 127.0.0.1:8080 /api.json HTTP/1.1" 0.001, 127.0.0.1, "http://127.0.0.1:8080/swagger/", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.54"
+2023-03-30 16:08:15.213 {2877b899fa23511794ae590ccd3aee81} 404 "GET http 127.0.0.1:8080 /favicon.ico HTTP/1.1" 0.000, 127.0.0.1, "http://127.0.0.1:8080/swagger/", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.54"
+2023-03-30 16:11:58.626 {d0cc229e2e245117d6f66e30f586205a} 200 "GET http 127.0.0.1:8080 /swagger HTTP/1.1" 0.000, 127.0.0.1, "", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.54"
+2023-03-30 16:11:58.739 {f89ddca42e245117d7f66e3010409a92} 200 "GET http 127.0.0.1:8080 /api.json HTTP/1.1" 0.001, 127.0.0.1, "http://127.0.0.1:8080/swagger/", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.54"
+2023-03-30 16:12:47.138 {b0eaaae939245117299ade4cdd909d3e} 200 "GET http 127.0.0.1:8080 /swagger HTTP/1.1" 0.001, 127.0.0.1, "", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.54"
+2023-03-30 16:12:47.229 {98f408ef392451172a9ade4c1b3d422b} 200 "GET http 127.0.0.1:8080 /api.json HTTP/1.1" 0.002, 127.0.0.1, "http://127.0.0.1:8080/swagger/", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.54"
+2023-03-30 16:13:05.466 {3003242e3e24511772949a176e3e9712} 200 "GET http 127.0.0.1:8080 /swagger HTTP/1.1" 0.000, 127.0.0.1, "", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.54"
+2023-03-30 16:13:05.567 {08150c343e24511773949a1763f897da} 200 "GET http 127.0.0.1:8080 /api.json HTTP/1.1" 0.002, 127.0.0.1, "http://127.0.0.1:8080/swagger/", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.54"
+2023-03-30 16:13:20.290 {e817b07d4024511774949a1749e447d1} 200 "POST http 127.0.0.1:8080 /hello HTTP/1.1" 4.900, 127.0.0.1, "", "PostmanRuntime/7.31.1"
+2023-03-30 16:16:21.948 {d80ac5d86a245117899daa5b4e557a50} 200 "POST http 127.0.0.1:8080 /hello HTTP/1.1" 4.641, 127.0.0.1, "", "PostmanRuntime/7.31.1"
+2023-03-30 16:18:48.925 {c02a8a168d245117aeae410549335351} 200 "POST http 127.0.0.1:8080 /hello HTTP/1.1" 4.553, 127.0.0.1, "", "PostmanRuntime/7.31.1"
+2023-03-30 16:21:13.638 {20be4ec9ae2451176560834e02365922} 200 "POST http 127.0.0.1:8080 /hello HTTP/1.1" 4.533, 127.0.0.1, "", "PostmanRuntime/7.31.1"
+2023-03-30 16:22:50.979 {d8acb36ac524511719b3542da75a8ddc} 200 "POST http 127.0.0.1:8080 /hello HTTP/1.1" 4.675, 127.0.0.1, "", "PostmanRuntime/7.31.1"
+2023-03-30 16:26:29.216 {504e9e42f82451170ac4a11bec6c5c48} 200 "POST http 127.0.0.1:8080 /hello HTTP/1.1" 4.543, 127.0.0.1, "", "PostmanRuntime/7.31.1"
+2023-03-30 16:27:07.641 {c0a6ac35012551175bb0d10e5613e6c7} 200 "POST http 127.0.0.1:8080 /hello HTTP/1.1" 4.530, 127.0.0.1, "", "PostmanRuntime/7.31.1"
+2023-03-30 16:28:22.796 {10ccf29f12255117235c2b4a795b17b6} 200 "POST http 127.0.0.1:8080 /hello HTTP/1.1" 4.888, 127.0.0.1, "", "PostmanRuntime/7.31.1"
+2023-03-30 16:36:12.440 {1094540d8025511735f9321fd3773ae9} 200 "POST http 127.0.0.1:8080 /hello HTTP/1.1" 4.545, 127.0.0.1, "", "PostmanRuntime/7.31.1"
+2023-03-30 16:40:05.949 {607bbe6cb62551171c3cfe546d3ef167} 200 "POST http 127.0.0.1:8080 /hello HTTP/1.1" 4.524, 127.0.0.1, "", "PostmanRuntime/7.31.1"
+2023-03-30 16:46:05.223 {f80830040a2651178e69df382b08f576} 200 "POST http 127.0.0.1:8080 /hello HTTP/1.1" 4.776, 127.0.0.1, "", "PostmanRuntime/7.31.1"
+2023-03-30 16:47:37.699 {789e47991f2651178f69df38da10bbfe} 200 "POST http 127.0.0.1:8080 /hello HTTP/1.1" 4.556, 127.0.0.1, "", "PostmanRuntime/7.31.1"

+ 0 - 0
resource/public/html/.gitkeep


+ 0 - 0
resource/public/plugin/.gitkeep


+ 0 - 0
resource/public/resource/css/.gitkeep


+ 0 - 0
resource/public/resource/image/.gitkeep


+ 0 - 0
resource/public/resource/js/.gitkeep


+ 0 - 0
resource/template/.gitkeep


+ 30 - 0
router/router.go

@@ -0,0 +1,30 @@
+package router
+
+import (
+	"github.com/gogf/gf/v2/net/ghttp"
+	"go-gpt/internal/controller"
+)
+
+func MiddlewareCORS(r *ghttp.Request) {
+
+	corsOptions := r.Response.DefaultCORSOptions()
+	//corsOptions.AllowDomain = []string{"goframe.org", "baidu.com"}
+	r.Response.CORS(corsOptions)
+
+	r.Response.CORSDefault()
+
+	r.Middleware.Next()
+}
+func BindController(group *ghttp.RouterGroup) {
+	//DomeRouter(group)
+
+	group.Group("/api/v1", func(group *ghttp.RouterGroup) {
+		group.Middleware(ghttp.MiddlewareHandlerResponse, MiddlewareCORS)
+	})
+}
+
+func DomeRouter(group *ghttp.RouterGroup) {
+	group.Bind(
+		controller.Hello,
+	)
+}

+ 0 - 0
utility/.gitkeep