Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 39 additions & 50 deletions app/api/v1/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,63 +5,14 @@
from concurrent.futures import ProcessPoolExecutor
import asyncio
import logging
import json
from app.services.stack_service import generate_techstack
from app.services.gpt_service import generate_aboutme, resume_update
from app.services.github_service import get_github_profile_and_repos
from app.config.settings import settings



router = APIRouter()

# 이력서 생성 api
@router.post("/api/ai/resumes", response_model=ResumeResponse)
async def generate_resume(request: ResumeRequest):
logging.basicConfig(level=logging.INFO)

# 각 레포지토리 요약을 멀티프로세싱으로 처리
with ProcessPoolExecutor() as executor:
loop = asyncio.get_event_loop()
tasks = [
loop.run_in_executor(executor, process_repository, repo_url, request.githubID, request.githubName, request.requirements)
for repo_url in request.selectedRepo
]
try:
# 실패 시 예외를 발생시키고 에러 메시지를 리턴
project_summaries = await asyncio.gather(*tasks)

except Exception as e:
logging.error(f"Error processing repositories: {e}")
return {"error": f"Error processing repositories: {str(e)}"}

# # aboutme techstack 생성
# aboutme_techstack = create_aboutme_techstack(project_summaries)


# 레포 이름
repo_name = "/".join(str(request.selectedRepo[0]).rstrip('/').split('/')[-2:])


# techstack 생성
techstack = generate_techstack(settings.gh_token, repo_name)
aboutme = generate_aboutme(settings.openai_api_key)

print(aboutme)


# 최종 이력서 응답 생성
resume_response = ResumeResponse(
projects=project_summaries,
techStack=techstack,
aboutMe=aboutme
# aboutMe=aboutme_techstack.aboutMe
)
return resume_response




@router.put("/api/ai/resumes", response_model=ResumeResponseDto)
async def update_resume(request: UpdateRequestDto):
try:
Expand Down Expand Up @@ -89,4 +40,42 @@ async def update_resume(request: UpdateRequestDto):

except Exception as e:
print(f"Error in update_resume: {e}")
raise HTTPException(status_code=500, detail="An error occurred while updating the resume.")
raise HTTPException(status_code=500, detail="An error occurred while updating the resume.")


# 이력서 생성 api
@router.post("/api/ai/resumes", response_model=ResumeResponse)
async def generate_resume(request: ResumeRequest):
logging.basicConfig(level=logging.INFO)

# 각 레포지토리 요약을 멀티프로세싱으로 처리
with ProcessPoolExecutor() as executor:
loop = asyncio.get_event_loop()
tasks = [
loop.run_in_executor(executor, process_repository, request.template, repo_url, request.githubID, request.githubName, request.requirements)
for repo_url in request.selectedRepo
]
try:
# 실패 시 예외를 발생시키고 에러 메시지를 리턴
project_data = await asyncio.gather(*tasks)

except Exception as e:
logging.error(f"Error processing repositories: {e}")
return {"error": f"Error processing repositories: {str(e)}"}

# 레포 이름
repo_name = "/".join(str(request.selectedRepo[0]).rstrip('/').split('/')[-2:])

# 공동생성 부분
techStack = generate_techstack(settings.gh_token, repo_name)
aboutMe = generate_aboutme(settings.openai_api_key)

resume_response = ResumeResponse(
template=request.template,
techStack=techStack,
aboutMe=aboutMe,
projects=project_data
)
print(resume_response)

return resume_response
63 changes: 63 additions & 0 deletions app/api/v1/routes2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from fastapi import APIRouter, HTTPException
from app.dto.resume_dto import ResumeRequest, ResumeResponse, BasicDto, freedom_dto, gitfolio_dto, star_dto
from app.dto.resume_modify_dto import UpdateRequestDto,ResumeResponseDto
from app.services.api_service import process_repository, create_repo_start_end_date
from concurrent.futures import ProcessPoolExecutor
import asyncio
import logging
import json
from app.services.stack_service import generate_techstack
from app.services.gpt_service import generate_aboutme, resume_update, generate_project_title, generate_role_and_task
from app.services.github_service import get_github_profile_and_repos
from app.config.settings import settings



router = APIRouter()
# 기존 코드 백업용
# 이력서 생성 api
@router.post("/api/ai/resumes", response_model=ResumeResponse)
async def generate_resume(request: ResumeRequest):
logging.basicConfig(level=logging.INFO)

# 각 레포지토리 요약을 멀티프로세싱으로 처리
with ProcessPoolExecutor() as executor:
loop = asyncio.get_event_loop()
tasks = [
loop.run_in_executor(executor, process_repository, repo_url, request.githubID, request.githubName, request.requirements)
for repo_url in request.selectedRepo
]
try:
# 실패 시 예외를 발생시키고 에러 메시지를 리턴
project_summaries = await asyncio.gather(*tasks)

except Exception as e:
logging.error(f"Error processing repositories: {e}")
return {"error": f"Error processing repositories: {str(e)}"}

# 레포 이름
repo_name = "/".join(str(request.selectedRepo[0]).rstrip('/').split('/')[-2:])

# techstack 생성
techstack = generate_techstack(settings.gh_token, repo_name)
aboutme = generate_aboutme(settings.openai_api_key)

# # 선택적 구성 생성
# role_and_task = generate_role_and_task(settings.openai_api_key)
# trouble_shooting = generate_trouble_shooting(settings.openai_api_key)
# star = generate_star_summary(settings.openai_api_key)


print("==========")
print(aboutme)

# 최종 이력서 응답 생성
resume_response = ResumeResponse(
template=request.template,
project_summaries=project_summaries,
)
print("==================")
print(resume_response)

return resume_response
# return JSONResponse(content=resume_response.dict())
5 changes: 4 additions & 1 deletion app/config/settings.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import List
from pydantic_settings import BaseSettings
from app.config.constant import GPT_MODEL, MAX_TOTAL_TOKENS, PROMPT_TOKEN_RESERVE, MAX_OUTPUT_TOKENS, MAX_CONTENT_TOKENS, DEFAULT_DATA, CODE_DATA, PR_DATA, COMMIT_DATA, PROJECT_DATA, REPO_DIRECTORY, FILE_EXTENSIONS
from app.prompts.resume_prompt import CODE_SUMMARY_PROMPT, PR_SUMMARY_PROMPT, COMMIT_DIFF_SUMMARY_PROMPT, FINAL_SUMMARY_PROMPT, FINAL_PROJECT_PROMPT, SIMPLIFY_PROJECT_PROMPT, ABOUTME_TECHSTACK_PROMPT, ABOUTME_PROMPT, RESUME_UPDATE_PROMPT, PROJECT_TITLE_PROMPT
from app.prompts.resume_prompt import CODE_SUMMARY_PROMPT, PR_SUMMARY_PROMPT, COMMIT_DIFF_SUMMARY_PROMPT, FINAL_SUMMARY_PROMPT, FINAL_PROJECT_PROMPT, SIMPLIFY_PROJECT_PROMPT, ABOUTME_TECHSTACK_PROMPT, ABOUTME_PROMPT, RESUME_UPDATE_PROMPT, PROJECT_TITLE_PROMPT, ROLE_AND_TASK_PROMPT, TROUBLE_SHOOTING_PROMPT, STAR_PROMPT
class Settings(BaseSettings):
# API 키
openai_api_key: str
Expand Down Expand Up @@ -40,6 +40,9 @@ class Settings(BaseSettings):
aboutme_prompt: str = ABOUTME_PROMPT
resume_update_prompt: str = RESUME_UPDATE_PROMPT
project_title_prompt: str = PROJECT_TITLE_PROMPT
role_and_task_prompt:str = ROLE_AND_TASK_PROMPT
trouble_shooting_prompt:str = TROUBLE_SHOOTING_PROMPT
star_prompt:str = STAR_PROMPT

class Config:
env_file = ".env"
Expand Down
18 changes: 13 additions & 5 deletions app/dto/resume_dto.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from pydantic import BaseModel, HttpUrl
from typing import List
from typing import List, Union
from app.dto.resume_modify_dto import StarDto, TroubleShootingDto


# 요청 데이터 모델
class ResumeRequest(BaseModel):
Expand All @@ -8,16 +10,22 @@ class ResumeRequest(BaseModel):
personalRepo: HttpUrl
selectedRepo: List[HttpUrl]
requirements: str
template: str

# 응답 데이터 모델 - 프로젝트 정보
# 응답 데이터 모델 - 프로젝트 정보(공통DTO)
class Project(BaseModel):
projectName: str
projectStartedAt: str # YYYY-MM-DD 형식
projectEndedAt: str # YYYY-MM-DD 형식
skillSet: str
projectDescription: str
roleAndTask: List[str] # BASIC 템플릿에서 사용
repoLink: HttpUrl

class StarProject(Project):
star: StarDto
class GitfolioProject(Project):
troubleShooting: TroubleShootingDto

# gpt 프로젝트 요약문, json형태
class GptProject(BaseModel):
projectName: str
Expand All @@ -31,7 +39,7 @@ class GptAboutmeTechstack(BaseModel):

# 응답 데이터 모델 - 전체 이력서
class ResumeResponse(BaseModel):
projects: List[Project]
template: str
techStack: List[str]
aboutMe: str

projects: List[Union[Project, StarProject, GitfolioProject]]
17 changes: 16 additions & 1 deletion app/dto/resume_modify_dto.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,19 @@ class UpdateRequestDto(BaseModel):
resumeInfo: ResumeResponseDto

class ProjectTitleDto(BaseModel):
projectTitle: str
projectTitle: str

class RoleAndTaskDto(BaseModel):
roleAndTask: List[str]

class TroubleShootingDto(BaseModel):
problem: str
hypothesis: str
tring: str
result: str

class StarDto(BaseModel):
situation: str
task: str
action: str
result: str
38 changes: 36 additions & 2 deletions app/prompts/resume_prompt.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
)

FINAL_PROJECT_PROMPT = (
"Do not use code blocks (```), but markdown formatting such as bold or lists is allowed. Provide plain text instead of code blocks."
"Write concisely and clearly, highlighting your unique strengths rather than common development details."
)

Expand Down Expand Up @@ -61,15 +62,48 @@
"3. Use metaphorical or creative expressions to enhance engagement, avoiding direct repetition of the input text.\n"
"4. Ensure each point reflects the provided company values and GitHub data."
)

# 이력서 재생성
RESUME_UPDATE_PROMPT = (
"Do not use code blocks (```), but markdown formatting such as bold or lists is allowed. Provide plain text instead of code blocks."
"Update the provided `selected_text` based on the user's request. "
"Modify only the specified text, and ensure the updated text aligns with the tone and style of the surrounding context. "
"Return only the modified text without altering the structure or other parts of the resume."
)

# 프로젝트 이름 생성
PROJECT_TITLE_PROMPT = (

"Return the best project title as plain text. "
"Do not include any additional explanation, formatting, or context. "
"Only provide the title itself."
)
# 맡은 업무 생성
ROLE_AND_TASK_PROMPT = (
"Do not use code blocks (```), but markdown formatting such as bold or lists is allowed. Provide plain text instead of code blocks."
"Create a summary of the main roles and responsibilities based on the provided data. "
"Use bullet points to list the key actions and tasks performed. Each point should:\n"
"- Begin with an action verb.\n"
"- Be concise and specific.\n"
"- Clearly reflect the user's contributions and achievements.\n\n"
"- Follow this pattern:"
"- Performed [specific action] to achieve [specific result], improving/enhancing [specific metric] by [quantifiable amount]. "
"- Identified [specific issue] and implemented [specific action], resulting in a performance improvement of [quantifiable amount]."
"- Utilized [specific tool or library] to develop/implement [specific functionality or feature]. "
"For example:\n"
"- Designed and implemented Redis caching to improve API response times by 30%.\n"
"- Refactored MongoDB queries to reduce average query time by 55.4%.\n"
"- Developed an event-driven architecture using Kafka for real-time notifications."
)
# 트러블슈팅 생성
TROUBLE_SHOOTING_PROMPT = (
"Do not use code blocks (```), but markdown formatting such as bold or lists is allowed. Provide plain text instead of code blocks."
)

# star기법 기반 생성
STAR_PROMPT = (
"Do not use code blocks (```), but markdown formatting such as bold or lists is allowed. Provide plain text instead of code blocks."
"The output should be generated in the following format:\n\n"
"- **Situation**: [Background and goals of the project]\n"
"- **Task**: [Challenges or problems addressed]\n"
"- **Action**: [Specific actions taken to solve the problem]\n"
"- **Result**: [Outcomes and improvements, including measurable metrics if possible]"
)
Loading