Skip to content

Commit 82d9fe5

Browse files
committed
reorganize
1 parent 6b0b61c commit 82d9fe5

File tree

6 files changed

+0
-1123
lines changed

6 files changed

+0
-1123
lines changed

lib/algora/admin/admin.ex

Lines changed: 0 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -24,145 +24,6 @@ defmodule Algora.Admin do
2424

2525
require Logger
2626

27-
defmodule JobPostingPrediction do
28-
@moduledoc false
29-
use Ecto.Schema
30-
use Instructor.Validator
31-
32-
alias Algora.Organizations
33-
34-
@llm_doc """
35-
## Field Descriptions:
36-
- tech_stack: List of technologies used in the job posting (e.g. ["Ruby", "Rails", "PostgreSQL"])
37-
- countries: List of 2-letter ISO country codes (e.g. ["US", "CA"])
38-
- regions: List of regions (e.g. ["EMEA", "LATAM"])
39-
- location: Location of the job posting (e.g. "Remote", "San Francisco, CA", "London/Berlin")
40-
- seniority: Seniority level (e.g. "Senior", "Mid-Senior", "Entry-Level")
41-
- company_url: Company website URL which can be derived from email (e.g. example.com)
42-
"""
43-
@primary_key false
44-
embedded_schema do
45-
embeds_many :job_postings, JobPosting, primary_key: false do
46-
field(:title, :string)
47-
field(:description, :string)
48-
field(:tech_stack, {:array, :string})
49-
field(:company_name, :string)
50-
field(:company_url, :string)
51-
field(:location, :string)
52-
field(:countries, {:array, :string})
53-
field(:regions, {:array, :string})
54-
field(:compensation, :string)
55-
field(:seniority, :string)
56-
end
57-
end
58-
59-
@impl true
60-
def validate_changeset(changeset) do
61-
changeset
62-
end
63-
64-
def seed_jobs(jobs) do
65-
jobs
66-
|> Task.async_stream(&seed/1, timeout: :infinity, max_concurrency: 50)
67-
|> Enum.to_list()
68-
end
69-
70-
def seed(job) do
71-
with domain when not is_nil(domain) <- Util.to_domain(job.company_url),
72-
{:ok, org} <- fetch_or_create_user(domain, %{hiring: true, tech_stack: job.tech_stack}),
73-
{:ok, org} <-
74-
org
75-
|> change(
76-
Map.merge(
77-
%{
78-
domain: org.domain || domain,
79-
hiring_subscription: :trial,
80-
billing_name: org.billing_name || job.company_name,
81-
billing_address: org.billing_address || job.location,
82-
executive_name: org.executive_name || job.company_name,
83-
executive_role: org.executive_role || job.seniority
84-
},
85-
if org.handle do
86-
%{}
87-
else
88-
%{handle: Organizations.ensure_unique_org_handle(job.company_name)}
89-
end
90-
)
91-
)
92-
|> Repo.update() do
93-
Repo.insert(%JobPosting{
94-
status: :processing,
95-
id: Nanoid.generate(),
96-
user_id: org.id,
97-
company_name: org.name,
98-
company_url: org.website_url,
99-
title: job.title,
100-
description: job.description,
101-
tech_stack: job.tech_stack,
102-
location: job.location,
103-
compensation: job.compensation,
104-
seniority: job.seniority,
105-
countries: job.countries,
106-
regions: job.regions
107-
})
108-
end
109-
end
110-
111-
def fetch_or_create_user(domain, opts) do
112-
case Repo.one(from o in User, where: o.domain == ^domain, limit: 1) do
113-
%User{} = user ->
114-
{:ok, user}
115-
116-
_ ->
117-
res = Organizations.onboard_organization_from_domain(domain, opts)
118-
res
119-
end
120-
end
121-
end
122-
123-
def classify_jobs(jobs) do
124-
batches = Enum.chunk_every(jobs, 10)
125-
126-
batches
127-
|> Enum.with_index()
128-
|> Enum.flat_map(fn {jobs, index} ->
129-
case classify_batch(jobs, index) do
130-
{:ok, predictions} ->
131-
predictions.job_postings
132-
133-
{:error, error} ->
134-
Logger.error("Failed to classify batch #{index}: #{inspect(error)}")
135-
[]
136-
end
137-
end)
138-
end
139-
140-
def classify_batch(jobs, index) do
141-
text = Enum.join(jobs, "\n\n")
142-
143-
Github.Client.run_cached("classify_jobs_#{index}", fn ->
144-
Instructor.chat_completion(
145-
model: "gpt-4o-mini",
146-
response_model: JobPostingPrediction,
147-
max_retries: 2,
148-
messages: [
149-
%{
150-
role: "user",
151-
content: """
152-
Your purpose is to turn arbitrary job postings into structured data.
153-
154-
Return a distinct entry for each job. Some paragraphs may contain multiple jobs.
155-
156-
Turn following job postings into structured data:
157-
158-
#{text}
159-
"""
160-
}
161-
]
162-
)
163-
end)
164-
end
165-
16627
def seed_job(opts \\ %{}) do
16728
with {:ok, user} <- Repo.fetch_by(User, handle: opts.org.handle),
16829
{:ok, user} <- user |> change(opts.org) |> Repo.update(),

lib/algora/settings/settings.ex

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -244,26 +244,4 @@ defmodule Algora.Settings do
244244
def set_subscription_price(price) do
245245
set("subscription", %{"price" => Algora.MoneyUtils.serialize(price)})
246246
end
247-
248-
def get_hn_job_ids do
249-
case get("hn_job_ids") do
250-
%{"ids" => ids} when is_list(ids) -> ids
251-
_ -> nil
252-
end
253-
end
254-
255-
def set_hn_job_ids(ids) when is_list(ids) do
256-
set("hn_job_ids", %{"ids" => ids})
257-
end
258-
259-
def get_hn_job_seekers do
260-
case get("hn_job_seekers") do
261-
%{"handles" => handles} when is_list(handles) -> handles
262-
_ -> nil
263-
end
264-
end
265-
266-
def set_hn_job_seekers(handles) when is_list(handles) do
267-
set("hn_job_seekers", %{"handles" => handles})
268-
end
269247
end

0 commit comments

Comments
 (0)