docs(project): 切换为AI工程化开发模式

This commit is contained in:
bruce
2026-09-01 11:41:09 +08:00
parent 38f1b15d1c
commit b7db30ec84
13 changed files with 109 additions and 676 deletions
+10 -10
View File
@@ -73,18 +73,18 @@ audit/ 日志、证据与版本追踪
详细边界参见 [架构设计](docs/architecture.md),Agent 的目标、工具和状态约定参见 [Agent 契约](docs/agent-contract.md),开发顺序参见 [实施路线图](docs/roadmap.md)。 详细边界参见 [架构设计](docs/architecture.md),Agent 的目标、工具和状态约定参见 [Agent 契约](docs/agent-contract.md),开发顺序参见 [实施路线图](docs/roadmap.md)。
## 学习与开发方式 ## AI开发方式
JobRadar 同时是实际项目和 Agent 学习项目,采用“逐阶段、逐课、手动实现”的协作方式: JobRadar采用“阶段目标驱动、AI直接实现”的开发方式:
1. 我先说明本课目标、核心原理以及它在完整系统中的位置。 1. 用户确认当前阶段目标、业务边界和验收重点。
2. 对照 Java、Spring 和常见后端设计解释 Python、Django 与 Agents SDK 的差异。 2. AI先检查仓库现状,给出修改方案和涉及文件。
3. 我提供本课所需的完整参考代码、运行命令、预期结果和常见错误。 3. AI直接生成或修改代码、迁移、配置、测试与必要文档。
4. 你根据讲解亲手把代码写入 JobRadar,不直接复制一个已完成项目。 4. AI执行静态检查、自动化测试和安全检查,并如实报告未覆盖项。
5. 你完成后,我检查正确性、可读性、Agent 设计和安全边界,并解释问题。 5. 用户根据可运行结果和页面效果进行业务验收。
6. 当前一课达到验收标准后,再开始下一课。 6. 当前阶段稳定后,再进入下一阶段或扩展更多工具。
默认情况下,我不会直接替你写入业务代码,也不会一次性生成后续全部模块。只有你明确要求我落地某段代码时,我才修改项目文件。详细约定参见 [学习协作说明](docs/learning-guide.md)。 实现应保持增量、小步、可验证。不会为了展示一次性生成所有未来模块,也不会将尚未运行验证的规划描述为已完成功能。详细约定参见 [AI开发约定](docs/development-guide.md)。
## 本地运行 ## 本地运行
@@ -212,4 +212,4 @@ JobRadar 仅用于个人岗位信息整理与求职辅助。使用前应确认
当前版本:`0.1.0-dev` 当前版本:`0.1.0-dev`
当前阶段:[阶段一第1课“Django项目配置与开发/生产环境拆分”](docs/lessons/01_Agent工程基线/1_1_Django项目配置与开发生产环境拆分/README.md)已经创建,等待学习者手动完成项目配置拆分。 当前阶段:架构与Agent契约已经确定,下一步由AI直接实现阶段一工程基线。
+56
View File
@@ -0,0 +1,56 @@
# JobRadar AI开发约定
## 开发模式
JobRadar不再采用课程式手动编码。后续由AI根据阶段目标直接生成和修改代码,用户主要负责业务方向、关键选择和结果验收。
## 每次开发流程
1. 检查Git状态、现有实现、依赖和相关文档。
2. 说明修改方案、涉及文件、风险和预期结果。
3. 在授权范围内直接完成代码、配置、数据库迁移、测试和文档改动。
4. 执行与改动匹配的验证,不以静态检查替代未执行的集成行为。
5. 汇报实际完成内容、验证结果、剩余风险和建议下一步。
6. 只有用户明确要求提交时才执行本地Git提交,默认不推送远程。
## 生成原则
- 以当前阶段的最小完整闭环为边界,不提前生成无法验证的未来模块。
- 优先使用OpenAI Agents SDK、Django等选定技术的原生能力,不引入无明确需求的兼容层。
- 所有Agent外部行为通过类型明确、权限受控、可审计的工具执行。
- 确定性规则、评分和数据写入由代码工具完成,不让模型随意生成最终业务事实。
- 新增代码遵循现有目录、命名、类型注解和中文注释风格。
- 保留用户已有变更,不覆盖无关文件,不提交密钥、Cookie和本地配置。
## 验证要求
根据改动范围选择并执行:
- Python语法编译和代码质量检查。
- Django系统检查与迁移检查。
- 模型、Service、工具和视图测试。
- Agent结构化输出、工具调用、失败路径和人工确认测试。
- 公网部署配置与Django部署安全检查。
- Git差异、敏感信息和提交范围检查。
无法运行的验证必须明确说明原因,不能仅凭代码阅读宣称通过。
## 交付要求
每次交付至少说明:
- 完成了什么功能。
- 修改了哪些核心文件。
- 执行了哪些验证及其结果。
- 是否存在需要用户提供的域名、账号、API Key或网站授权。
- 当前工作区是否已提交、是否推送。
## 用户确认边界
以下事项仍需用户明确决定:
- 目标招聘网站和允许的访问方式。
- 外部付费服务、模型及调用预算。
- 公网域名、服务器和部署平台。
- 可能产生费用或对外副作用的操作。
- 自动投递、自动联系、删除历史数据等高风险能力。
-82
View File
@@ -1,82 +0,0 @@
# JobRadar 学习协作说明
## 项目定位
JobRadar不只是需要交付的岗位系统,也是用于系统学习正规Agent开发的实战项目。学习目标包括Agents SDK运行循环、工具设计、状态管理、人工确认、可观测性、评测、公网Web应用和工程化部署。
## 默认协作方式
每次只推进一课,流程如下:
1. 回顾上一课成果和遗留问题。
2. 说明本课完成后能够做什么。
3. 解释新概念是什么、为什么需要以及在JobRadar中的位置。
4. 使用Java、Spring或常见后端设计进行必要对照。
5. 给出本课完整参考代码,并逐段解释执行顺序和设计原因。
6. 明确代码应该写入哪个文件以及如何运行。
7. 给出预期结果、常见错误、调试方法和验收标准。
8. 学习者手动完成代码。
9. 对学习者代码进行检查,不直接覆盖已有实现。
10. 当前课通过后再继续下一课。
## 每课内容结构
每课原则上包含:
- 本课目标
- 前置知识
- 架构位置
- 核心原理
- Java或Spring对照
- 完整参考代码
- 关键代码解析
- 手动实现步骤
- 运行命令与预期结果
- 常见错误与排查方法
- 课堂练习
- 自检清单
- 验收标准
- 本课小结
## 代码边界
- 默认由学习者手动编写业务代码。
- 我提供参考代码、解释、提示、测试思路和审查反馈。
- 未经明确要求,不直接向JobRadar写入本课业务实现。
- 不一次性生成未来阶段代码,不提前制造空模块。
- 不覆盖学习者已有实现;发现问题时先说明原因和修正方案。
- 用户明确要求代为修改时,先说明方案、涉及文件和预期结果,再执行改动。
## 练习约定
如果后续为课程创建练习文件,练习文件只包含注释形式的题目、操作提示、预期结果、自检项和验收标准,不包含导入语句、函数骨架、`pass`、测试数据、答案或运行记录。
参考答案与练习文件分离。学习者完成代码后,优先基于学习者实现进行讲解,而不是用参考答案覆盖。
## 验收方式
每课至少验证:
- 代码能够在`JobRadar` Conda环境中运行。
- Django系统检查或对应测试通过。
- 行为与本课预期结果一致。
- Agent工具真实执行,没有用自然语言伪造结果。
- 数据写入具备用户归属、幂等和审计边界。
- 密钥、Cookie和本地配置没有进入Git。
- 学习者能够说明关键代码为什么这样设计。
涉及Agent的课程还需要检查工具调用、结构化输出、trace、失败路径和人工确认边界,不能只检查最终文本是否看起来正确。
## 教学深度
学习者已有Java和数据库基础,因此不重复教授变量、类、SQL、事务等通用概念。课程重点解释:
- Python与Java在语言和工程组织上的差异。
- Django与Spring Boot在请求处理、ORM、配置和用户体系上的差异。
- Agents SDK与普通Service编排、工作流引擎及传统定时任务的差异。
- Agent何时自主决策,何时必须交给确定性工具或人工确认。
- 如何通过trace和eval判断一个Agent是否真正可靠。
## 当前起点
第一课[Django项目配置与开发/生产环境拆分](lessons/01_Agent工程基线/1_1_Django项目配置与开发生产环境拆分/README.md)已经创建。当前应阅读讲义、参考完整示例,然后手动拆分项目配置;完成后执行课程验收命令并提交代码供检查。
@@ -1,267 +0,0 @@
# 第1课:Django项目配置与开发/生产环境拆分
## 本课目标
完成本课后,你将能够:
1. 解释Django设置模块(settings module)如何被加载。
2. 将单一`settings.py`拆成公共、开发和生产三套配置。
3. 使用`DJANGO_SETTINGS_MODULE`选择运行环境。
4. 将生产密钥和域名移出Git仓库。
5. 使用Django部署检查发现危险配置。
本课只学习配置拆分,不接入PostgreSQL、Celery或Agents SDK。
## 前置知识
- 能运行`python manage.py check`和`python manage.py runserver`。
- 理解Python模块和`import`。
- 了解Spring Boot的Profile和`application-{profile}.yml`。
## 在JobRadar架构中的位置
JobRadar最终部署到公网,并需要数据库密码、模型API Key、招聘网站凭据等敏感配置。如果开发与生产共用一个`settings.py`,很容易出现以下问题:
- 将开发环境的`DEBUG = True`带到公网。
- 将生产密钥提交到Git。
- 本地SQLite和生产PostgreSQL配置互相覆盖。
- 本地地址、正式域名和HTTPS策略混在一起。
- Agent运行时读取了错误的模型或密钥。
因此,安全配置是用户系统和Agent功能之前的工程基线。
## 核心原理
### 1. settings本质上是Python模块
Django设置不是特殊配置格式,而是包含模块级变量的Python模块。例如:
```python
DEBUG = False
ALLOWED_HOSTS = ["jobradar.example.com"]
```
Django启动时读取`DJANGO_SETTINGS_MODULE`,然后导入该变量指定的Python模块:
```text
JobRadar.settings.development
JobRadar.settings.production
```
点号是Python包路径,不是文件系统斜杠。
### 2. 公共配置与环境差异分离
本课采用三层结构:
```text
JobRadar/
└── settings/
├── __init__.py
├── base.py
├── development.py
└── production.py
```
- `base.py`:应用、Middleware、模板、国际化等公共配置。
- `development.py`:开发密钥、`DEBUG = True`和本地地址。
- `production.py`:生产密钥、正式域名、HTTPS和安全Cookie。
`development.py`和`production.py`通过`from .base import *`继承公共配置。这种星号导入在普通业务代码中不推荐,但Django分层settings是一个边界明确的配置场景。
### 3. 与Spring Boot Profile对照
| Spring Boot | Django本课方案 |
| --- | --- |
| `application.yml` | `settings/base.py` |
| `application-dev.yml` | `settings/development.py` |
| `application-prod.yml` | `settings/production.py` |
| `spring.profiles.active=dev` | `DJANGO_SETTINGS_MODULE=JobRadar.settings.development` |
| `${DB_PASSWORD}` | `os.environ["DB_PASSWORD"]` |
| `@Profile`控制Bean | Django通常在settings中切换组件配置 |
最大的区别是:Spring配置主要是YAML/Properties,Django settings本身就是Python代码。它更灵活,也意味着不能在里面随意写复杂业务逻辑。
## 完整参考代码
参考目录位于本课的`reference/`中:
```text
reference/
├── settings/
│ ├── __init__.py
│ ├── base.py
│ ├── development.py
│ └── production.py
├── manage.py
├── asgi.py
└── wsgi.py
```
这些文件用于阅读和手动输入,不能直接覆盖当前项目。你需要理解每一处路径变化后,再把对应结构写入项目。
## 关键代码解析
### `BASE_DIR`为什么多一个`parent`
原始`settings.py`位于:
```text
JobRadar/settings.py
```
拆分后的`base.py`位于:
```text
JobRadar/settings/base.py
```
文件多进入了一层`settings`目录,因此项目根目录改为:
```python
BASE_DIR = Path(__file__).resolve().parent.parent.parent
```
如果仍使用两个`parent`,SQLite和模板目录都会指向错误位置。
### 为什么生产配置使用`os.environ[名称]`
```python
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
```
方括号读取在变量缺失时立即抛出`KeyError`,让生产进程启动失败。相比提供一个不安全默认值,这种“快速失败”(fail fast)更安全。
开发配置可以使用明确标记为仅限本地的默认密钥,但生产配置绝不能提供默认生产密钥。
### 为什么入口的默认环境不同
- `manage.py`默认开发配置,方便本地运行。
- `asgi.py`和`wsgi.py`默认生产配置,降低部署时误启用开发设置的风险。
- 命令行仍可通过`--settings`显式覆盖,便于检查两个环境。
## 手动实现步骤
1. 在`JobRadar`包内创建`settings`目录及`__init__.py`。
2. 参考`base.py`移动原`settings.py`的公共配置,并修正`BASE_DIR`。
3. 编写`development.py`和`production.py`。
4. 修改项目根目录的`manage.py`,默认指向开发配置。
5. 修改`JobRadar/asgi.py`和`JobRadar/wsgi.py`,默认指向生产配置。
6. 删除旧`JobRadar/settings.py`前,逐项确认内容已经迁移。
7. 分别运行开发和生产配置检查。
不要直接复制整个`reference`目录覆盖项目,因为参考文件的层级和真实文件位置并不完全相同。
## 运行方法
### 检查开发配置
```powershell
conda activate JobRadar
python manage.py check --settings=JobRadar.settings.development
```
预期结果:
```text
System check identified no issues (0 silenced).
```
### 检查生产配置的缺失密钥保护
先确保当前PowerShell没有设置课程变量:
```powershell
Remove-Item Env:DJANGO_SECRET_KEY -ErrorAction SilentlyContinue
python manage.py check --settings=JobRadar.settings.production
```
预期结果:命令失败,并明确提示缺少`DJANGO_SECRET_KEY`。这是安全保护生效,不是课程代码错误。
### 临时设置生产变量并检查
以下值只在当前PowerShell进程有效:
```powershell
$env:DJANGO_SECRET_KEY = "仅用于本地检查的长随机字符串-请勿用于生产"
$env:DJANGO_ALLOWED_HOSTS = "jobradar.example.com"
$env:DJANGO_CSRF_TRUSTED_ORIGINS = "https://jobradar.example.com"
python manage.py check --settings=JobRadar.settings.production
python manage.py check --deploy --settings=JobRadar.settings.production
```
普通`check`应通过。`check --deploy`可能继续提示HSTS时长等部署建议;本课重点是能区分错误和安全告警,不要求为了消除告警而盲目开启尚未理解的配置。
检查完成后清理临时变量:
```powershell
Remove-Item Env:DJANGO_SECRET_KEY
Remove-Item Env:DJANGO_ALLOWED_HOSTS
Remove-Item Env:DJANGO_CSRF_TRUSTED_ORIGINS
```
## 常见错误
### 错误1:`No module named 'JobRadar.settings.development'`
原因通常是:
- 没有创建`settings/__init__.py`。
- 包或模块名称拼错。
- 旧`settings.py`仍存在,导致目录结构未正确调整。
### 错误2:SQLite文件出现在`JobRadar/`包内
原因是拆分后没有为`BASE_DIR`增加一层`parent`。
### 错误3:生产检查仍然使用开发配置
先查看命令是否传入:
```text
--settings=JobRadar.settings.production
```
也可以运行:
```powershell
python manage.py diffsettings --settings=JobRadar.settings.production
```
### 错误4:把生产密钥写入`production.py`
生产密钥必须由服务器部署环境注入。Git中的示例只能写变量名和虚假示例,不能包含真实值。
### 错误5:`ALLOWED_HOSTS = ["*"]`
星号允许任意Host,失去了Django主机头校验的主要意义。公网项目应填写明确域名;本地开发单独允许`127.0.0.1`和`localhost`。
## 课堂练习
练习要求见[practice.py](practice.py)。该文件只有题目和验收标准,你的实际代码应写入JobRadar项目配置文件中。
## 自检清单
- [ ] 能解释`DJANGO_SETTINGS_MODULE`的作用。
- [ ] 能说明`base.py`中为什么使用三个`parent`。
- [ ] 开发环境默认开启`DEBUG`,生产环境固定关闭。
- [ ] 生产环境缺少密钥时会快速失败。
- [ ] 生产域名和CSRF可信来源来自外部配置。
- [ ] ASGI/WSGI默认指向生产配置。
- [ ] Git差异中没有真实密钥。
## 验收标准
1. `python manage.py check --settings=JobRadar.settings.development`通过。
2. 缺少`DJANGO_SECRET_KEY`时,生产配置检查按预期失败。
3. 临时提供生产变量后,普通生产配置检查通过。
4. `python manage.py makemigrations --check --dry-run --settings=JobRadar.settings.development`显示无遗漏迁移。
5. `git diff --check`通过。
6. `git diff`中没有真实密钥、Cookie或密码。
7. 学习者能解释开发和生产入口为何采用不同默认settings。
## 本课小结
本课没有增加业务功能,但建立了公网Agent项目的安全配置基础。Django通过`DJANGO_SETTINGS_MODULE`选择一个Python配置模块;公共设置放入`base.py`,开发和生产只覆盖差异。生产环境应关闭`DEBUG`、限制域名、启用HTTPS相关设置,并在缺少密钥时拒绝启动。
完成手动实现并通过验收后,下一课进入“Django用户系统与用户数据归属”。
@@ -1,43 +0,0 @@
# 第1课练习:Django项目配置与开发/生产环境拆分
#
# 练习目标:
# 1. 将当前单文件settings.py拆分为base、development和production三个配置模块。
# 2. 让本地管理命令默认使用开发配置,让ASGI和WSGI默认使用生产配置。
# 3. 验证生产密钥缺失时快速失败,提供临时变量后能够通过普通系统检查。
#
# 操作要求:
# 1. 在JobRadar包内创建settings目录和__init__.py。
# 2. 把公共配置迁移到base.py,并根据新目录层级修正BASE_DIR。
# 3. 在development.py中配置仅限本地使用的SECRET_KEY、DEBUG和ALLOWED_HOSTS。
# 4. 在production.py中从外部读取DJANGO_SECRET_KEY、DJANGO_ALLOWED_HOSTS和
# DJANGO_CSRF_TRUSTED_ORIGINS,固定关闭DEBUG并配置HTTPS安全项。
# 5. 调整manage.py、asgi.py和wsgi.py使用正确的默认配置模块。
# 6. 确认全部配置迁移后再删除旧settings.py。
#
# 预期结果:
# 1. 开发配置执行Django系统检查时通过。
# 2. 未设置DJANGO_SECRET_KEY时,生产配置检查明确失败。
# 3. 设置三个临时生产变量后,生产配置普通检查通过。
# 4. 项目根目录仍是BASE_DIR,SQLite和templates路径没有移动到JobRadar包中。
# 5. Git变更中不存在真实密钥、密码或Cookie。
#
# 自检问题:
# 1. DJANGO_SETTINGS_MODULE保存的是文件路径还是Python模块路径?
# 2. 为什么生产配置不应该为SECRET_KEY提供默认值?
# 3. 为什么DEBUG=False时必须正确设置ALLOWED_HOSTS?
# 4. 为什么manage.py和ASGI/WSGI选择不同的默认配置?
# 5. 为什么本课暂时不配置PostgreSQL和Agents SDK?
#
# 验收命令:
# python manage.py check --settings=JobRadar.settings.development
# python manage.py check --settings=JobRadar.settings.production
# python manage.py check --deploy --settings=JobRadar.settings.production
# python manage.py makemigrations --check --dry-run --settings=JobRadar.settings.development
# git diff --check
#
# 验收标准:
# 1. 能解释三个配置文件各自负责什么。
# 2. 能解释BASE_DIR层级变化。
# 3. 能复现生产密钥缺失时的失败,并确认这是预期安全行为。
# 4. 能区分普通系统检查错误与部署安全告警。
# 5. practice.py保持纯注释,不在此文件填写答案或运行记录。
@@ -1,14 +0,0 @@
"""JobRadar生产ASGI入口的参考实现。"""
import os
from django.core.asgi import get_asgi_application
# 部署入口默认选择生产配置,避免遗漏环境选择时启用DEBUG。
os.environ.setdefault(
"DJANGO_SETTINGS_MODULE",
"JobRadar.settings.production",
)
application = get_asgi_application()
@@ -1,24 +0,0 @@
#!/usr/bin/env python
"""JobRadar本地管理命令入口的参考实现。"""
import os
import sys
def main() -> None:
"""默认使用开发配置执行Django管理命令。"""
os.environ.setdefault(
"DJANGO_SETTINGS_MODULE",
"JobRadar.settings.development",
)
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"无法导入Django,请确认已经激活JobRadar Conda环境。"
) from exc
execute_from_command_line(sys.argv)
if __name__ == "__main__":
main()
@@ -1 +0,0 @@
"""JobRadar分环境配置包的参考入口。"""
@@ -1,77 +0,0 @@
"""JobRadar所有运行环境共享的Django配置参考。"""
from pathlib import Path
# base.py比原settings.py多位于一层settings目录中,因此需要向上三级到达项目根目录。
BASE_DIR = Path(__file__).resolve().parent.parent.parent
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
]
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
ROOT_URLCONF = "JobRadar.urls"
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [BASE_DIR / "templates"],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
WSGI_APPLICATION = "JobRadar.wsgi.application"
ASGI_APPLICATION = "JobRadar.asgi.application"
# 第一课保留SQLite,下一阶段学习PostgreSQL时再调整数据库配置。
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
}
}
AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]
LANGUAGE_CODE = "zh-hans"
TIME_ZONE = "Asia/Shanghai"
USE_I18N = True
USE_TZ = True
STATIC_URL = "static/"
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
@@ -1,16 +0,0 @@
"""JobRadar本地开发环境的Django配置参考。"""
import os
from .base import * # noqa: F403
# 默认值只能用于本机开发,生产环境不会导入本模块。
SECRET_KEY = os.getenv(
"DJANGO_SECRET_KEY",
"django-insecure-jobradar-local-development-only",
)
DEBUG = True
ALLOWED_HOSTS = ["127.0.0.1", "localhost"]
@@ -1,40 +0,0 @@
"""JobRadar公网生产环境的Django配置参考。"""
import os
from django.core.exceptions import ImproperlyConfigured
from .base import * # noqa: F403
def get_required_environment_value(name: str) -> str:
"""读取必需的生产变量,缺失或空白时立即阻止应用启动。"""
value = os.getenv(name, "").strip()
if not value:
raise ImproperlyConfigured(f"缺少必需的环境变量:{name}")
return value
def get_required_environment_list(name: str) -> list[str]:
"""读取逗号分隔的必需列表,并去除每一项两侧的空白。"""
raw_value = get_required_environment_value(name)
values = [item.strip() for item in raw_value.split(",") if item.strip()]
if not values:
raise ImproperlyConfigured(f"环境变量没有有效配置项:{name}")
return values
SECRET_KEY = get_required_environment_value("DJANGO_SECRET_KEY")
DEBUG = False
ALLOWED_HOSTS = get_required_environment_list("DJANGO_ALLOWED_HOSTS")
CSRF_TRUSTED_ORIGINS = get_required_environment_list(
"DJANGO_CSRF_TRUSTED_ORIGINS"
)
# HTTPS在反向代理终止时,Django通过该请求头识别原始请求协议。
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_CONTENT_TYPE_NOSNIFF = True
X_FRAME_OPTIONS = "DENY"
@@ -1,14 +0,0 @@
"""JobRadar生产WSGI入口的参考实现。"""
import os
from django.core.wsgi import get_wsgi_application
# 部署入口默认选择生产配置,避免遗漏环境选择时启用DEBUG。
os.environ.setdefault(
"DJANGO_SETTINGS_MODULE",
"JobRadar.settings.production",
)
application = get_wsgi_application()
+43 -88
View File
@@ -1,64 +1,41 @@
# JobRadar 实施路线图 # JobRadar 实施路线图
## 推进规则 ## 推进原则
本路线图用于确定学习顺序,不代表一次性生成所有代码。每个阶段继续拆成若干课,每次只开始当前一课: 项目按可运行成果分阶段实施。每个阶段由AI直接生成代码、迁移、测试和必要文档,但只实现当前阶段所需内容;完成自动验证和用户验收后,再扩大范围。
- 开课时先讲解原理、Agent职责和本课代码边界。 ## 阶段一:工程基线
- 提供可运行的参考代码,但由学习者手动写入项目。
- 学习者提交实现后进行代码检查和运行验证。
- 当前课验收通过后,才准备下一课。
- 不提前创建后续课程的业务代码或空目录。
- 阶段结束时安排回顾、评测和一个可展示的阶段成果。
## 阶段一:Agent 工程基线 目标:建立适合公网运行和持续开发的Django基础。
建议课程: - [ ] 拆分开发、测试和生产配置。
- [ ] 将密钥及本地配置移出版本库。
1. Django项目配置与开发/生产环境拆分。 - [ ] 接入Django用户认证和用户资料模型。
2. Django用户系统与用户数据归属。 - [ ] 为用户私有业务数据建立统一归属边界。
3. PostgreSQL迁移与Agent运行数据模型。 - [ ] 接入PostgreSQL并建立迁移基线。
4. OpenAI Agents SDK最小Agent与Runner。 - [ ] 接入OpenAI Agents SDK。
5. Agent Run、运行事件与工具调用持久化。 - [ ] 建立Agent Run、运行事件、工具调用和人工确认模型。
- [x] 初始化 Django 项目、Conda 环境和 Git 仓库。
- [x] 补充项目、架构、Agent 契约和路线图文档。
- [ ] 拆分开发、测试和生产配置,将密钥移出版本库。
- [ ] 接入 Django 用户认证和用户资料模型。
- [ ] 接入 PostgreSQL 并建立迁移基线。
- [ ] 接入 OpenAI Agents SDK。
- [ ] 建立 Agent Run、运行事件、工具调用和人工确认模型。
- [ ] 增加统一日志、测试和代码质量工具。 - [ ] 增加统一日志、测试和代码质量工具。
## 阶段二:最小 Agent 闭环 验收条件:开发与生产配置隔离,用户可以安全登录,PostgreSQL迁移通过,最小Agent运行数据可持久化。
建议课程: ## 阶段二:最小Agent闭环
1. Function Tool原理及第一个只读工具。 目标:证明系统具备真实、可观察的Agent运行循环。
2. Pydantic结构化输入与输出。
3. 多工具选择和Agent运行循环。
4. 运行预算、超时、异常与人工确认。
5. Agent轨迹页面和最小评测集。
- [ ] 定义岗位研究 Agent 的 instructions、输入、输出、工具、状态和人工确认点。 - [ ] 定义岗位研究Agent的instructions、输入、输出、工具和状态。
- [ ] 使用 Agents SDK 实现一个 Agent 和 Runner 入口。 - [ ] 使用Agents SDK实现Agent和Runner入口。
- [ ] 实现候选岗位查询、规则筛选和结果保存三个最小 Function Tool。 - [ ] 实现候选岗位查询、规则筛选和结果保存三个最小Function Tool。
- [ ] 设置最大轮次、超时和工具调用预算。 - [ ] 设置最大轮次、超时和工具调用预算。
- [ ] 保存工具调用、结果摘要、最终输出和 trace 标识。 - [ ] 保存工具调用、结果摘要、最终输出和trace标识。
- [ ] 在 WebUI 展示一次完整运行,而不只展示最终回答。 - [ ] 在WebUI展示一次完整运行,而不只展示最终回答。
- [ ] 建立最小评测集,覆盖正常结果、证据不足、工具失败和禁止操作。 - [ ] 建立最小评测集,覆盖正常结果、证据不足、工具失败和禁止操作。
验收条件:Agent 能自主选择并调用真实工具,输出结构化结果;页面可以查看工具轨迹,评测能识别没有调用必要工具的伪结果。 验收条件:Agent能自主调用真实工具并输出结构化结果,页面能够展示运行轨迹,评测可以识别未调用必要工具的伪结果。
## 阶段三:单站采集与筛选 ## 阶段三:单站采集与筛选
建议课程: 目标:通过真实工具稳定处理一个明确授权范围内的招聘网站。
1. 招聘网站适配器与工具边界。
2. HTTPX与Playwright采集。
3. 原始数据、标准化与幂等入库。
4. 硬性筛选工具和Agent调用。
5. 单站采集阶段项目。
- [ ] 确认首个招聘网站的服务条款和访问边界。 - [ ] 确认首个招聘网站的服务条款和访问边界。
- [ ] 定义站点适配器协议和原始岗位结构。 - [ ] 定义站点适配器协议和原始岗位结构。
@@ -66,78 +43,56 @@
- [ ] 增加限流、超时、重试和失败日志。 - [ ] 增加限流、超时、重试和失败日志。
- [ ] 定义岗位、企业和岗位来源模型。 - [ ] 定义岗位、企业和岗位来源模型。
- [ ] 标准化岗位名、地点、薪资、经验和学历。 - [ ] 标准化岗位名、地点、薪资、经验和学历。
- [ ] 完成来源岗位编号去重和内容变化识别。 - [ ] 完成岗位去重和内容变化识别。
- [ ] 建立排除词、黑名单和硬性筛选工具。 - [ ] 建立排除词、黑名单和硬性筛选工具。
- [ ] 实现岗位列表、详情和个人处理状态。 - [ ] 实现岗位列表、详情和个人处理状态。
验收条件:Agent 通过真实工具采集一个网站,所有岗位均可追溯到原始来源,确定性规则能解释淘汰原因。 验收条件:Agent通过真实工具采集一个网站,所有岗位可追溯到原始来源,确定性规则能够解释淘汰原因。
## 阶段四:企业联网研究 ## 阶段四:企业联网研究
建议课程: 目标:可靠判断企业主体和企业性质,并保留证据。
1. 企业研究任务拆解和证据模型。
2. 联网搜索工具与来源可信度。
3. 企业主体归一化和证据冲突。
4. 人工复核与可恢复运行。
- [ ] 确定合法、稳定的企业信息来源。 - [ ] 确定合法、稳定的企业信息来源。
- [ ] 建立企业别名、标准主体和证据模型。 - [ ] 建立企业别名、标准主体和证据模型。
- [ ] 实现企业研究工具,保存来源、时间和置信度。 - [ ] 实现企业研究工具,保存来源、时间和置信度。
- [ ] 实现多来源冲突检测和人工复核队列。 - [ ] 实现多来源冲突检测和人工复核队列。
- [ ] 保留自动判断和人工确认历史。 - [ ] 保留自动判断与人工确认历史。
验收条件:Agent 不会在证据不足时强行分类,企业结论包含可访问来源和查询时间。 验收条件:Agent不会在证据不足时强行分类,企业结论包含可访问来源和查询时间。
## 阶段五:评分、护栏与评测 ## 阶段五:评分、护栏与评测
建议课程: 目标:形成可解释、可测试的岗位推荐结果。
1. 个人画像和匹配分析契约。
2. 确定性评分工具。
3. Guardrail与越权防护。
4. Agent行为评测和回归用例。
5. Trace分析和提示词迭代。
- [ ] 定义个人岗位画像和技能偏好。 - [ ] 定义个人岗位画像和技能偏好。
- [ ] 完善 Agent 结构化输出模型和运行状态。 - [ ] 完善Agent结构化输出和运行状态。
- [ ] 实现匹配分析工具与确定性评分工具。 - [ ] 实现匹配分析工具和确定性评分工具。
- [ ] 保存维度分数、风险扣分、理由和版本。 - [ ] 保存维度分数、风险扣分、理由和版本。
- [ ] 增加输入/输出 guardrail 和人工确认节点。 - [ ] 增加输入/输出guardrail和人工确认节点。
- [ ] 建立工具选择、证据引用、拒绝越权和故障恢复评测。 - [ ] 建立工具选择、证据引用、拒绝越权和故障恢复评测。
- [ ] 使用 trace 分析失败运行并形成回归用例。 - [ ] 使用trace分析失败运行并形成回归用例。
验收条件:每个总分都能分解到权重和证据;Agent 必须调用必要工具,不得编造外部事实或越过硬规则。 验收条件:每个总分都能分解到权重和证据;Agent必须调用必要工具,不得编造外部事实或越过硬规则。
## 阶段六:调度、公网部署与展示 ## 阶段六:调度、公网部署与展示
建议课程: 目标:让系统能够在公网长期、安全运行。
1. Celery异步Agent Run。 - [ ] 接入Celery、Redis和Celery Beat。
2. 定时任务、幂等和故障恢复。
3. Agent工作台与执行过程展示。
4. Docker Compose和生产配置。
5. HTTPS公网部署与最终演示。
- [ ] 接入 Celery、Redis 和 Celery Beat。
- [ ] 实现运行幂等、指数退避、暂停和恢复。 - [ ] 实现运行幂等、指数退避、暂停和恢复。
- [ ] 完成 Agent 任务中心与实时运行状态展示。 - [ ] 完成Agent任务中心和实时运行状态展示。
- [ ] 增加高分新岗位通知。 - [ ] 增加高分新岗位通知。
- [ ] 增加第二个站点工具,验证扩展边界。 - [ ] 增加第二个站点工具,验证扩展边界。
- [ ] 使用 Nginx/Caddy、生产级应用服务器和 HTTPS 部署。 - [ ] 使用Nginx/Caddy、生产级应用服务器和HTTPS部署。
- [ ] 增加安全响应头、登录限流和数据库备份。 - [ ] 增加安全响应头、登录限流和数据库备份。
- [ ] 整理演示用 Agent 轨迹、评测结果和架构说明。 - [ ] 整理演示用Agent轨迹、评测结果和架构说明。
验收条件:系统可以在公网安全运行,用户能同时查看岗位结果与 Agent 执行过程,站点故障不会破坏其他运行。 验收条件:系统可以在公网安全运行,用户能同时查看岗位结果与Agent执行过程,单个站点故障不会破坏其他运行。
## 第一轮开发前待确认 ## 第一阶段启动前待确认
1. 首个招聘网站及允许使用的访问方式。 1. PostgreSQL运行位置和连接方式。
2. 岗位、城市、薪资、经验和学历范围。 2. OpenAI模型、调用预算和API Key注入方式。
3. 必须包含和必须排除的关键词。 3. 公网部署平台、域名和HTTPS证书管理方式。
4. 企业性质、行业和公司规模偏好。 4. 首个目标招聘网站及允许使用的访问方式。
5. 评分维度及初始权重。
6. 企业信息数据源。
7. OpenAI 模型、调用预算及单次运行上限。
8. 运行频率、单次岗位数量和通知渠道。
9. 公网域名、服务器和 HTTPS 证书管理方式。