Skip to content

Commit

Permalink
添加积分不足时的报错 + 简历分析 (#281)
Browse files Browse the repository at this point in the history
* 添加积分不足时的报错 + 简历分析

* make check

* 修改

---------

Co-authored-by: zhuwenliang <[email protected]>
  • Loading branch information
juniaoshaonian and zhuwenliang authored Nov 28, 2024
1 parent 104aa2a commit d96a4b0
Show file tree
Hide file tree
Showing 18 changed files with 472 additions and 31 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ cover.out
/internal/cases/internal/integration/logs
/internal/skill/internal/integration/logs
/internal/feedback/internal/integration/logs
/internal/resume/internal/integration/logs
/config/cert/

local_test.go
Expand Down
3 changes: 2 additions & 1 deletion internal/ai/internal/errs/code.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package errs

var (
SystemError = ErrorCode{Code: 516001, Msg: "系统错误"}
SystemError = ErrorCode{Code: 516001, Msg: "系统错误"}
InsufficientCredit = ErrorCode{Code: 516002, Msg: "积分不足"}
)

type ErrorCode struct {
Expand Down
49 changes: 33 additions & 16 deletions internal/ai/internal/web/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import (
"github.com/ecodeclub/ginx"
"github.com/ecodeclub/ginx/session"
"github.com/ecodeclub/webook/internal/ai/internal/domain"
"github.com/ecodeclub/webook/internal/ai/internal/errs"
"github.com/ecodeclub/webook/internal/ai/internal/service"
"github.com/ecodeclub/webook/internal/ai/internal/service/llm/handler/credit"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
)

type Handler struct {
Expand All @@ -28,31 +31,45 @@ func (h *Handler) PrivateRoutes(server *gin.Engine) {
func (h *Handler) LLMAsk(ctx *ginx.Context, req LLMRequest, sess session.Session) (ginx.Result, error) {
uid := sess.Claims().Uid
resp, err := h.generalSvc.LLMAsk(ctx, uid, req.Biz, req.Input)
if err != nil {
switch {
case errors.Is(err, credit.ErrInsufficientCredit):
return ginx.Result{
Code: errs.InsufficientCredit.Code,
Msg: errs.InsufficientCredit.Msg,
}, nil
case err == nil:
return ginx.Result{
Data: LLMResponse{
Amount: resp.Amount,
RawResult: resp.Answer,
},
}, nil
default:
return systemErrorResult, err
}
return ginx.Result{
Data: LLMResponse{
Amount: resp.Amount,
RawResult: resp.Answer,
},
}, nil
}

func (h *Handler) AnalysisJd(ctx *ginx.Context, req JDRequest, sess session.Session) (ginx.Result, error) {
uid := sess.Claims().Uid
resp, err := h.jdSvc.Evaluate(ctx, uid, req.JD)
if err != nil {
switch {
case errors.Is(err, credit.ErrInsufficientCredit):
return ginx.Result{
Code: errs.InsufficientCredit.Code,
Msg: errs.InsufficientCredit.Msg,
}, nil
case err == nil:
return ginx.Result{
Data: JDResponse{
Amount: resp.Amount,
TechScore: h.newJD(resp.TechScore),
BizScore: h.newJD(resp.BizScore),
PosScore: h.newJD(resp.PosScore),
},
}, nil
default:
return systemErrorResult, err
}
return ginx.Result{
Data: JDResponse{
Amount: resp.Amount,
TechScore: h.newJD(resp.TechScore),
BizScore: h.newJD(resp.BizScore),
PosScore: h.newJD(resp.PosScore),
},
}, nil

}

Expand Down
20 changes: 20 additions & 0 deletions internal/resume/internal/domain/analysis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package domain

const (
BizResumeSkillKeyPoints = "biz_resume_skill_keypoints"
BizSkillsRewrite = "biz_skills_rewrite"
BizResumeProjectKeyPoints = "biz_resume_project_keypoints"
BizResumeProjectRewrite = "biz_resume_project_rewrite"
BizResumeJobsKeyPoints = "biz_resume_jobs_keypoints"
BizResumeJobsRewrite = "biz_resume_jobs_rewrite"
)

type ResumeAnalysis struct {
Amount int64
// 技能
RewriteSkills string
// 项目
RewriteProject string
// 工作经历
RewriteJobs string
}
2 changes: 2 additions & 0 deletions internal/resume/internal/errs/code.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package errs

var (
SystemError = ErrorCode{Code: 515001, Msg: "系统错误"}
// InsufficientCredit 这个不管说是客户端错误还是服务端错误,都有点勉强,所以随便用一个 5
InsufficientCredit = ErrorCode{Code: 515002, Msg: "积分不足"}
)

type ErrorCode struct {
Expand Down
135 changes: 135 additions & 0 deletions internal/resume/internal/integration/analysis_handler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package integration

import (
"context"
"errors"
"fmt"
"net/http"
"testing"

"github.com/ecodeclub/ekit/iox"
"github.com/ecodeclub/ginx/session"
"github.com/ecodeclub/webook/internal/ai"
aimocks "github.com/ecodeclub/webook/internal/ai/mocks"
"github.com/ecodeclub/webook/internal/cases"
"github.com/ecodeclub/webook/internal/resume/internal/domain"
"github.com/ecodeclub/webook/internal/resume/internal/integration/startup"
"github.com/ecodeclub/webook/internal/resume/internal/web"
"github.com/ecodeclub/webook/internal/test"
"github.com/gin-gonic/gin"
"github.com/gotomicro/ego/core/econf"
"github.com/gotomicro/ego/server/egin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"go.uber.org/mock/gomock"
)

type AnalysisTestSuite struct {
suite.Suite
server *egin.Component
}

func (a *AnalysisTestSuite) SetupSuite() {
ctrl := gomock.NewController(a.T())
aiSvc := aimocks.NewMockService(ctrl)
aiSvc.EXPECT().Invoke(gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, req ai.LLMRequest) (ai.LLMResponse, error) {
switch req.Biz {
case domain.BizResumeSkillKeyPoints:
return ai.LLMResponse{
Tokens: 100,
Amount: 100,
Answer: fmt.Sprintf("skill的keypoints %s", req.Input[0]),
}, nil
case domain.BizSkillsRewrite:
return ai.LLMResponse{
Tokens: 200,
Amount: 200,
Answer: fmt.Sprintf("%s:%s", req.Input[0], req.Input[1]),
}, nil
case domain.BizResumeProjectKeyPoints:
return ai.LLMResponse{
Tokens: 150,
Amount: 150,
Answer: fmt.Sprintf("project的keypoints %s", req.Input[0]),
}, nil
case domain.BizResumeProjectRewrite:
return ai.LLMResponse{
Tokens: 220,
Amount: 220,
Answer: fmt.Sprintf("%s:%s", req.Input[0], req.Input[1]),
}, nil
case domain.BizResumeJobsKeyPoints:
return ai.LLMResponse{
Tokens: 300,
Amount: 300,
Answer: fmt.Sprintf("jobs的keypoints %s", req.Input[0]),
}, nil
case domain.BizResumeJobsRewrite:
return ai.LLMResponse{
Tokens: 400,
Amount: 400,
Answer: fmt.Sprintf("%s:%s", req.Input[0], req.Input[1]),
}, nil
default:
return ai.LLMResponse{}, errors.New("mock Err")
}
}).AnyTimes()
module := startup.InitModule(&cases.Module{}, &ai.Module{Svc: aiSvc})

hdl := module.AnalysisHandler
econf.Set("server", map[string]any{"contextTimeout": "1s"})
server := egin.Load("server").Build()
server.Use(func(ctx *gin.Context) {
ctx.Set(session.CtxSessionKey,
session.NewMemorySession(session.Claims{
Uid: uid,
}))
})
hdl.PublicRoutes(server.Engine)
a.server = server
}

func (a *AnalysisTestSuite) TestAnalysis() {
testCases := []struct {
name string

req web.AnalysisReq

wantCode int
wantResp test.Result[web.AnalysisResp]
}{
{
name: "分析简历",
req: web.AnalysisReq{
Resume: "resume",
},
wantCode: 200,
wantResp: test.Result[web.AnalysisResp]{
Data: web.AnalysisResp{
Amount: 1370,
RewriteSkills: "resume:skill的keypoints resume",
RewriteJobs: "resume:jobs的keypoints resume",
RewriteProject: "resume:project的keypoints resume",
},
},
},
}
for _, tc := range testCases {
a.T().Run(tc.name, func(t *testing.T) {
req, err := http.NewRequest(http.MethodPost,
"/resume/analysis", iox.NewJSONReader(tc.req))
req.Header.Set("content-type", "application/json")
require.NoError(t, err)
recorder := test.NewJSONResponseRecorder[web.AnalysisResp]()
a.server.ServeHTTP(recorder, req)
require.Equal(t, tc.wantCode, recorder.Code)
data := recorder.MustScan()
assert.Equal(t, tc.wantResp, data)
})
}
}

func TestAnalysisModule(t *testing.T) {
suite.Run(t, new(AnalysisTestSuite))
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"testing"
"time"

"github.com/ecodeclub/webook/internal/ai"

"github.com/ecodeclub/ekit/iox"
"github.com/ecodeclub/ekit/sqlx"
"github.com/ecodeclub/webook/internal/resume/internal/domain"
Expand Down Expand Up @@ -62,7 +64,9 @@ func (s *ExperienceTestSuite) SetupSuite() {

module := startup.InitModule(&cases.Module{
ExamineSvc: examSvc,
})
},
&ai.Module{},
)
econf.Set("server", map[string]any{"contextTimeout": "1s"})
server := egin.Load("server").Build()

Expand Down
5 changes: 4 additions & 1 deletion internal/resume/internal/integration/project_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"strconv"
"testing"

"github.com/ecodeclub/webook/internal/ai"

"github.com/ecodeclub/ekit/iox"
"github.com/ecodeclub/ekit/slice"
"github.com/ecodeclub/ginx/session"
Expand Down Expand Up @@ -82,7 +84,8 @@ func (s *ProjectTestSuite) SetupSuite() {
module := startup.InitModule(&cases.Module{
ExamineSvc: examSvc,
Svc: caseSvc,
})
},
&ai.Module{})
econf.Set("server", map[string]any{"contextTimeout": "1s"})
server := egin.Load("server").Build()
server.Use(func(ctx *gin.Context) {
Expand Down
6 changes: 5 additions & 1 deletion internal/resume/internal/integration/startup/wire.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package startup

import (
"github.com/ecodeclub/webook/internal/ai"
"github.com/ecodeclub/webook/internal/cases"
"github.com/ecodeclub/webook/internal/resume"
"github.com/ecodeclub/webook/internal/resume/internal/repository"
Expand All @@ -13,7 +14,7 @@ import (
"github.com/google/wire"
)

func InitModule(caModule *cases.Module) *resume.Module {
func InitModule(caModule *cases.Module, aiModule *ai.Module) *resume.Module {
wire.Build(
testioc.InitDB,
dao.NewResumeProjectDAO,
Expand All @@ -22,10 +23,13 @@ func InitModule(caModule *cases.Module) *resume.Module {
repository.NewExperience,
service.NewService,
service.NewExperienceService,
service.NewAnalysisService,
wire.FieldsOf(new(*cases.Module), "ExamineSvc"),
wire.FieldsOf(new(*cases.Module), "Svc"),
wire.FieldsOf(new(*ai.Module), "Svc"),
web.NewHandler,
web.NewExperienceHandler,
web.NewAnalysisHandler,
wire.Struct(new(resume.Module), "*"),
)
return new(resume.Module)
Expand Down
11 changes: 8 additions & 3 deletions internal/resume/internal/integration/startup/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit d96a4b0

Please sign in to comment.