defyour_function(a, b): let c = a c = b # error: c is immutable
if c != b: var c = b stuff()
let和var声明支持类型说明符以及模式,还支持延迟初始化:
1 2 3 4 5 6 7 8 9 10
defyour_function(): let x: Int8 = 42 let y: Int64 = 17
let z: Int8 if x != 0: z = 1 else: z = foo() use(z)
Note that let and var are completely opt-in when in def declarations. You can still use implicitly declared values as with Python, and they get function scope as usual.
structMyPair: var first: Int var second: Int def __init__(self&, first: Int, second: Int): self.first = first self.second = second def __lt__(self, rhs: MyPair) -> Bool: returnself.first < rhs.first or (self.first == rhs.first and self.second < rhs.second)
从语法上讲,与 Python 类相比,结构体中的所有实例属性都必须使用 var 或 let 声明显式声明。
if ('serviceWorker'in navigator) { addEventListener('load', function () { navigator.serviceWorker.register('./path/to/service-worker.js'); }); }
深入service worker
在 service worker 中,您可以访问 $service-worker 模块,该模块为您提供所有静态资源、构建文件和预渲染页面的路径。还提供了一个应用程序版本字符串,您可以使用它来创建唯一的缓存名称以及部署的base路径。如果您的 Vite 配置指定了 define(用于全局变量替换),则这也将应用于服务工作者以及服务器/客户端构建。
// Create a unique cache name for this deployment constCACHE = `cache-${version}`;
constASSETS = [ ...build, // the app itself ...files // everything in `static` ];
self.addEventListener('install', (event) => { // Create a new cache and add all files to it asyncfunctionaddFilesToCache() { const cache = await caches.open(CACHE); await cache.addAll(ASSETS); }
event.waitUntil(addFilesToCache()); });
self.addEventListener('activate', (event) => { // Remove previous cached data from disk asyncfunctiondeleteOldCaches() { for (const key ofawait caches.keys()) { if (key !== CACHE) await caches.delete(key); } }
event.waitUntil(deleteOldCaches()); });
self.addEventListener('fetch', (event) => { // ignore POST requests etc if (event.request.method !== 'GET') return;
{ "exports":{ ".":{ "types":"./dist/index.d.ts", // changing `svelte` to `default` is a breaking change: "svelte":"./dist/index.js" "default":"./dist/index.js" }, // removing this is a breaking change: "./foo":{ "types":"./dist/foo.d.ts", "svelte":"./dist/foo.js", "default":"./dist/foo.js" }, // adding this is ok: "./bar":{ "types":"./dist/bar.d.ts", "svelte":"./dist/bar.js", "default":"./dist/bar.js" } } }
使用 npm i -D @sveltejs/adapter-node 进行安装,然后将适配器添加到您的svelte.config.js文件中:
svelte.config.js
1 2 3 4 5 6 7
import adapter from'@sveltejs/adapter-node';
exportdefault { kit: { adapter: adapter() } };
Deploying
首先,使用npm run build构建您的应用程序。这将在适配器选项中指定的输出目录(默认为build)中创建生产服务器。
要运行应用程序,您需要输出目录、项目的package.json文件以及node_modules中的生产依赖项。可以通过复制package.json和package-lock.json并运行npm ci --omit dev来生成生产依赖项(如果您的应用程序没有任何依赖项,则可以跳过此步骤)。然后,您可以使用以下命令启动应用程序:
使用npm i -D @sveltejs/adapter-static进行安装,然后将适配器添加到您的 svelte.config.js 文件中:
svelte.config.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
import adapter from'@sveltejs/adapter-static';
exportdefault { kit: { adapter: adapter({ // default options are shown. On some platforms // these options are set automatically — see below pages: 'build', assets: 'build', fallback: null, precompress: false, strict: true }) } };
…and add the prerender option to your root layout:
…并将prerender 选项添加到您的根布局中:
src/routes/+layout.js
1 2
// This can be false if you're using a fallback (i.e. SPA mode) export const prerender = true;
You must ensure SvelteKit’s trailingSlash option is set appropriately for your environment. If your host does not render /a.html upon receiving a request for /a then you will need to set trailingSlash: 'always' to create /a/index.html instead.
# If you're using pnpm, add this step then change the commands and cache key below to use `pnpm` # - name: Install pnpm # uses: pnpm/action-setup@v2 # with: # version: 8
使用npm i -D @sveltejs/adapter-netlify进行安装,然后将适配器添加到您的 svelte.config.js 文件中:
svelte.config.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
import adapter from'@sveltejs/adapter-netlify';
exportdefault { kit: { // default options are shown adapter: adapter({ // if true, will create a Netlify Edge Function rather // than using standard Node-based functions edge: false,
// if true, will split your app into multiple functions // instead of creating a single one for the entire app. // if `edge` is true, this option cannot be used split: false }) } };
exportdefault { kit: { adapter: adapter({ // will create a Netlify Edge Function using Deno-based // rather than using standard Node-based functions edge: true }) } };
exportconstload = async (event) => { const context = event.platform.context; console.log(context); // shows up in your functions log in the Netlify app };
exportconst config = { isr: { // Expiration time (in seconds) before the cached asset will be re-generated by invoking the Serverless Function. // Setting the value to `false` means it will never expire. expiration: 60,
// Random token that can be provided in the URL to bypass the cached version of the asset, by requesting the asset // with a __prerender_bypass=<token> cookie. // // Making a `GET` or `HEAD` request with `x-prerender-revalidate: <token>` will force the asset to be re-validated. bypassToken: BYPASS_TOKEN,
// List of valid query parameters. Other parameters (such as utm tracking codes) will be ignored, // ensuring that they do not result in content being regenerated unnecessarily allowQuery: ['search'] } };
<script> let a = 0; let b = 0; let total = 0; asyncfunctionadd() { const response = awaitfetch('/api/add', { method: 'POST', body: JSON.stringify({ a, b }), headers: { 'content-type': 'application/json' } }); total = await response.json(); } </script>
<script> import { page } from'$app/stores'; /** @type {import('./$types').PageData} */ exportlet data; // we can access `data.posts` because it's returned from // the parent layout `load` function $: index = data.posts.findIndex(post => post.slug === $page.params.slug); $: next = data.posts[index - 1]; </script>
// cache the page for the same length of time // as the underlying data setHeaders({ age: response.headers.get('age'), 'cache-control': response.headers.get('cache-control') });
/** @type {import('./$types').PageLoad} */ exportasyncfunctionload({ fetch, depends }) { // load reruns when `invalidate('https://api.example.com/random-number')` is called... const response = awaitfetch('https://api.example.com/random-number');
// ...or when `invalidate('app:random')` is called depends('app:random');
return { number: await response.json() }; }
src/routes/random-number/+page.svelte
1 2 3 4 5 6 7 8 9 10 11 12 13 14
<script> import { invalidate, invalidateAll } from '$app/navigation'; /** @type {import('./$types').PageData} */ export let data;
function rerunLoadFunction() { // any of these will cause the `load` function to re-run invalidate('app:random'); invalidate('https://api.example.com/random-number'); invalidate(url => url.href.includes('random-number')); invalidateAll(); } </script>
<p>random number: {data.number}</p> <button on:click={rerunLoadFunction}>Update random number</button>
const user = await db.getUser(email); cookies.set('sessionid', await db.createSession(user));
return { success: true }; }, register: async (event) => { // TODO register the user } };
src/routes/login/+page.svelte
1 2 3 4 5 6 7 8 9 10 11 12
<script> /** @type {import('./$types').PageData} */ export let data; /** @type {import('./$types').ActionData} */ export let form; </script>
{#if form?.success} <!-- this message is ephemeral; it exists because the page was rendered in response to a form submission. it will vanish if the user reloads --> <p>Successfully logged in! Welcome back, {data.user.name}</p> {/if}
<form method="POST" use:enhance={({ form, data, action, cancel, submitter }) => { // `form` is the `<form>` element // `data` is its `FormData` object // `action` is the URL to which the form is posted // `cancel()` will prevent the submission // `submitter` is the `HTMLElement` that caused the form to be submitted
return async ({ result, update }) => { // `result` is an `ActionResult` object // `update` is a function which triggers the logic that would be triggered if this callback wasn't set }; }} >
<script> import { enhance, applyAction } from '$app/forms';
/** @type {import('./$types').ActionData} */ export let form; </script>
<form method="POST" use:enhance={({ form, data, action, cancel }) => { // `form` is the `<form>` element // `data` is its `FormData` object // `action` is the URL to which the form is posted // `cancel()` will prevent the submission
return async ({ result }) => { // `result` is an `ActionResult` object if (result.type === 'error') { await applyAction(result); } }; }} >
通常情况下,SvelteKit 首先在服务器上呈现您的页面,并将该 HTML 发送到客户端进行水合作用。如果您将 ssr 设置为 false,则会呈现一个空的“外壳”页面。如果您的页面无法在服务器上呈现(例如,因为使用了仅限于浏览器的全局变量,如 document),则这很有用,但在大多数情况下不建议这样做(请参见附录)。
+page.js
1
export const ssr = false;
如果你在根 +layout.js 中添加 export const ssr = false,那么整个应用程序将只在客户端渲染 —— 这基本上意味着你把应用程序变成了单页应用。
你可能会想知道,如果我们不能使用自己的存储库,我们如何能够使用 $page.data 和其他应用商店。答案是服务器上的应用商店使用 Svelte 的上下文 API - 存储库附加到组件树中,并通过setContext进行订阅时检索 getContext。我们可以对自己的存储库执行相同的操作:
src/routes/+layout.svelte
1 2 3 4 5 6 7 8
<script> import { setContext } from 'svelte'; import { writable } from 'svelte/store'; /** @type {import('./$types').LayoutData} */ export let data; // Create a store and update it when necessary... const user = writable(); $: user.set(data.user); // ...and add it to the context for child components to access setContext('user', user); </script>
src/routes/user/+page.svelte
1 2 3 4 5 6
<script> import { getContext } from 'svelte'; // Retrieve user store from context const user = getContext('user'); </script>
在Replit,我们投入了大量资源来建立从头开始训练自己的大型语言模型所需的基础设施。在本文中,我们将概述我们如何训练LLM(Large Language Models),从原始数据到部署到用户面向生产环境。我们将讨论沿途遇到的工程挑战以及如何利用我们认为构成现代LLM堆栈的供应商:Databricks、Hugging Face和MosaicML。
Transformer模型是机器学习中最令人兴奋的新发展之一。它们在论文Attention is All You Need中被介绍。Transformer可以用于写故事、文章、诗歌,回答问题,翻译语言,与人类聊天,甚至可以通过对人类来说很难的考试!但是它们到底是什么呢?你会很高兴地知道,Transformer模型的架构并不复杂,它只是一些非常有用组件的串联,并且每个组件都有自己的功能。在本篇文章中,您将了解所有这些组件。
简而言之,Transformer的作用是什么?想象一下你在手机上写短信。每输入一个单词后,你可能会得到三个建议的单词。例如,如果你输入“Hello, how are”,手机可能会建议下一个单词为“you”或“your”。当然,如果你继续选择手机中的建议单词,很快就会发现这些单词组成的信息毫无意义。如果你看每一组连续的3或4个单词,则它们可能有意义,但这些单词并不构成任何有意义的句子。这是因为手机使用的模型没有携带消息整体上下文,只是预测最近几个字后更可能出现哪个字。相反地,“Transformer”可以跟踪所编写内容背景,并且这就是它们编写文本使其具有意义之处所在。
我们可以训练这样一个大型网络,但是通过添加关键步骤:Attention(注意力)组件,我们可以极大地改进它。在开创性论文《Attention is All you Need》中引入的注意力机制是Transformer模型的关键成分之一,也是它们如此有效的原因之一。下面将解释注意力机制,但现在先想象它作为一种向文本中每个单词添加上下文的方式。
简而言之,注意力机制的作用是将句子(或文本片段)中的单词在词嵌入中靠近。这样,在句子“Money in the bank”中,“bank”一词将被移动到“money”的附近。同样,在句子“The bank of the river”中,“bank”一词将被移动到“river”的附近。这样,两个句子中修改后的单词“bank”都会携带周围单词的某些信息,为其添加上下文。