|
| 1 | +# Lab 6: Retrieve Recommended Resume |
| 2 | + |
| 3 | +In this lab, we will add an API endpoint to retrieve the recommended resume and return it. |
| 4 | + |
| 5 | +Here are the steps to complete: |
| 6 | + |
| 7 | +1. Create a function `get_recommendation` in `ai.py` that takes the job description |
| 8 | +1. Create an api endpoint `api_recommend_resume` in `main.py` |
| 9 | + - Path `/api/job-posts/{job_post_id}/recommend` |
| 10 | + - Takes `job_post_id` as a parameter |
| 11 | + - Calls the `get_recommendation` function created in previous step |
| 12 | + - Returns the matching job application |
| 13 | + |
| 14 | +Write tests along with the code. |
| 15 | + |
| 16 | +## High Level Overview |
| 17 | + |
| 18 | +1. We want to implement `get_recommendatation` in `ai.py`. First think about how we will test this function. |
| 19 | +1. One way can be to add some resumes to the vector store, then call `get_recommendation` with a job description and see whether it is returning the right one |
| 20 | +1. Write a test to do the above. It will fail when you run the tests, since we have not implemented it yet |
| 21 | +1. Make the test pass by implementing the functionality in `get_recommendation` |
| 22 | +1. Next we need to implement the API. Again -- how will we test this? |
| 23 | +1. Maybe we can create a dummy job post with a job description and then upload some resumes. Then we can call the recommendation API using the test client and see if we get the correct output. |
| 24 | +1. Write this a pyunit test that does this. |
| 25 | +1. Then implement the api endpoint till it passes |
| 26 | +1. We are done! |
| 27 | + |
| 28 | +## Hints |
| 29 | + |
| 30 | +### How do I test get_recommendatation? |
| 31 | + |
| 32 | +<details> |
| 33 | +<summary>Answer</summary> |
| 34 | + |
| 35 | +```python |
| 36 | +def test_retrieval(vector_store): |
| 37 | + for id, filename in enumerate(os.listdir("test/resumes")): |
| 38 | + with open(f"test/resumes/{filename}", "rb") as f: |
| 39 | + content = f.read() |
| 40 | + ingest_resume_for_recommendataions(content, filename, resume_id=id, vector_store=vector_store) |
| 41 | + result = get_recommendation("I am looking for an expert in AI", vector_store) |
| 42 | + assert "Andrew" in result.page_content |
| 43 | +``` |
| 44 | +</details> |
| 45 | + |
| 46 | +### How do I implement get_recommendation? |
| 47 | + |
| 48 | +<details> |
| 49 | +<summary>Answer</summary> |
| 50 | + |
| 51 | +```python |
| 52 | +def get_recommendation(job_description, vector_store): |
| 53 | + retriever = vector_store.as_retriever(search_kwargs={"k": 1}) |
| 54 | + results = retriever.invoke(job_description) |
| 55 | + return results[0] |
| 56 | +``` |
| 57 | +</details> |
| 58 | + |
| 59 | +### How do I test the new API endpoint? |
| 60 | + |
| 61 | +<details> |
| 62 | +<summary>Answer</summary> |
| 63 | + |
| 64 | +```python |
| 65 | +def test_recommendation_api(db_session, client): |
| 66 | + job_board = JobBoard(slug="test", logo_url="http://example.com") |
| 67 | + db_session.add(job_board) |
| 68 | + db_session.commit() |
| 69 | + db_session.refresh(job_board) |
| 70 | + job_post = JobPost(title="AI Engineer", |
| 71 | + description="I am looking for a generalist who can work in python and typescript", |
| 72 | + job_board_id = job_board.id) |
| 73 | + db_session.add(job_post) |
| 74 | + db_session.commit() |
| 75 | + db_session.refresh(job_post) |
| 76 | + test_resumes = [ |
| 77 | + ( 'Andrew', 'Ng', '[email protected]', 'ProfileAndrewNg.pdf'), |
| 78 | + ( 'Koudai', 'Aono', '[email protected]', 'ProfileKoudaiAono.pdf') |
| 79 | + ] |
| 80 | + for first_name, last_name, email, filename in test_resumes: |
| 81 | + post_data = { |
| 82 | + "first_name": first_name, |
| 83 | + "last_name": last_name, |
| 84 | + "email": email, |
| 85 | + "job_post_id": job_post.id |
| 86 | + } |
| 87 | + with open(f"test/resumes/{filename}", "rb") as f: |
| 88 | + response = client.post("/api/job-applications", data=post_data, files={"resume": (filename, f, "application/pdf")}) |
| 89 | + response = client.get(f"/api/job-posts/{job_post.id}/recommend") |
| 90 | + assert response.status_code == 200 |
| 91 | + data = response.json() |
| 92 | + assert data['first_name'] == 'Koudai' |
| 93 | + assert data['last_name'] == 'Aono' |
| 94 | +``` |
| 95 | +</details> |
| 96 | + |
| 97 | +### How do I implement the new API endpoint? |
| 98 | + |
| 99 | +<details> |
| 100 | +<summary>Answer</summary> |
| 101 | + |
| 102 | +```python |
| 103 | +@app.get("/api/job-posts/{job_post_id}/recommend") |
| 104 | +async def api_recommend_resume( |
| 105 | + job_post_id, |
| 106 | + db: Session = Depends(get_db), |
| 107 | + vector_store = Depends(get_vector_store)): |
| 108 | + |
| 109 | + job_post = db.get(JobPost, job_post_id) |
| 110 | + if not job_post: |
| 111 | + raise HTTPException(status_code=400) |
| 112 | + job_description = job_post.description |
| 113 | + recommended_resume = get_recommendation(job_description, vector_store) |
| 114 | + application_id = recommended_resume.metadata["_id"] |
| 115 | + job_application = db.get(JobApplication, application_id) |
| 116 | + return job_application |
| 117 | +``` |
| 118 | +</details> |
0 commit comments