背景
最近想找个和科研方向有点关联的实习。在北邮人论坛上按关键字“大模型”搜索,找比较新的,开投。看到理想有个自己弄的 MindGPT 用在车机上,感觉很有看头。投完之后 HR 当天回复,快两周后约面。
面试节奏说不上慢,一二面一起,一面是纯技术面,二面是 leader 聊天面,总共一个半小时解决战斗。面试体验很不错,面试官非常尊重人。
一面
时长:1h
- 自我介绍
- 文章,给面试官讲了一下论文的思路;面试官表示她以前做过一些 graph + 时序的工作,提出了一些关于 tokenization 部分很有意思的点;聊天的形式过了一下各种 tokenizer
- 面试官介绍了一下组里的工作
- Transformer 中 MHA 的公式
- 为什么 self-attention 中 \text{softmax}(\frac{QK^T}{\sqrt{d_k}})V 要除以 \sqrt{d_k}
- LayerNorm 和 BatchNorm 的区别
- 为什么用 LayerNorm
- Dot-product 换成别的行不行
- RoPE 相比其它位置编码什么好处
- Vanilla transformer 的位置编码的缺点
- 算法题:LeetCode 394. Decode String(OI/ACM 模式,我没调完面试官就要换二面了,事后发现是
std::stack::pop()
没有判空……)
#include <algorithm>
#include <cstdio>
#include <stack>
#include <iostream>
#include <string>
int main() {
std::string str;
std::cin >> str;
std::stack<int> times;
std::stack<char> st;
int tmp = 0;
for (int i = 0; i < str.length(); ++i) {
if (std::isdigit(str[i])) {
tmp *= 10;
tmp += str[i] - '0';
}
else if (str[i] == '[') {
times.push(tmp);
st.push('[');
tmp = 0;
}
else if (str[i] == ']') {
std::string word = "";
while (!st.empty() && st.top() != '[') {
word.push_back(st.top());
st.pop();
}
if (!st.empty())
st.pop();
if (!times.empty()) {
int time = times.top();
while (time--) {
for (int j = word.length() - 1; j >= 0; --j) {
st.push(word[j]);
}
}
times.pop();
// printf("WORD: %s\n", word.c_str());
word = "";
}
}
else if (!std::isdigit(str[i])) {
st.push(str[i]);
}
}
std::string res = "";
while (!st.empty()) {
char ch = st.top();
st.pop();
res.push_back(ch);
}
std::reverse(res.begin(), res.end());
std::cout << res;
}
C++二面
面试官是一位上古时代的 OIer,Pascal 选手,对 naive pascal compiler 十分的感兴趣。首先问了一些项目细节,尤其是关注代码编译异常检测这个方面。之后面试官开始介绍他们的工作,主要是一些 LLM + 代码生成用到车机里面的思路。这个思路相当新颖,因为一开始我以为 LLM 只是用来做分析/调用的,结果他们是用 LLM 直接做代码生产,所以灵活性非常强。
面试末尾面试官给了口头 offer,并表示会走一个不超过两周的 HR 流程。理想的工作地点分顺义总部和望京两个部分,这个团队在望京;实习生朝九晚六,而正式工要到晚上 8 点多。
后续
很“幸运”的赶上理想组织架构调整,实习 offer 审批全部被冻结了。从面试官本来觉得半个月会有可能,结果又等了一个月还是没办法过 HR,那就遗憾地错过啦。