This commit is contained in:
SteampsonJake 2023-04-04 16:50:01 -05:00 committed by GitHub
commit 129d522c50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 32 additions and 2419 deletions

View File

@ -1,98 +1,2 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.twitter.ann.faiss;
public class AlignedTableFloat32 {
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected AlignedTableFloat32(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(AlignedTableFloat32 obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
swigfaissJNI.delete_AlignedTableFloat32(swigCPtr);
}
swigCPtr = 0;
}
}
public void setTab(SWIGTYPE_p_faiss__AlignedTableTightAllocT_float_32_t value) {
swigfaissJNI.AlignedTableFloat32_tab_set(swigCPtr, this, SWIGTYPE_p_faiss__AlignedTableTightAllocT_float_32_t.getCPtr(value));
}
public SWIGTYPE_p_faiss__AlignedTableTightAllocT_float_32_t getTab() {
long cPtr = swigfaissJNI.AlignedTableFloat32_tab_get(swigCPtr, this);
return (cPtr == 0) ? null : new SWIGTYPE_p_faiss__AlignedTableTightAllocT_float_32_t(cPtr, false);
}
public void setNumel(long value) {
swigfaissJNI.AlignedTableFloat32_numel_set(swigCPtr, this, value);
}
public long getNumel() {
return swigfaissJNI.AlignedTableFloat32_numel_get(swigCPtr, this);
}
public static long round_capacity(long n) {
return swigfaissJNI.AlignedTableFloat32_round_capacity(n);
}
public AlignedTableFloat32() {
this(swigfaissJNI.new_AlignedTableFloat32__SWIG_0(), true);
}
public AlignedTableFloat32(long n) {
this(swigfaissJNI.new_AlignedTableFloat32__SWIG_1(n), true);
}
public long itemsize() {
return swigfaissJNI.AlignedTableFloat32_itemsize(swigCPtr, this);
}
public void resize(long n) {
swigfaissJNI.AlignedTableFloat32_resize(swigCPtr, this, n);
}
public void clear() {
swigfaissJNI.AlignedTableFloat32_clear(swigCPtr, this);
}
public long size() {
return swigfaissJNI.AlignedTableFloat32_size(swigCPtr, this);
}
public long nbytes() {
return swigfaissJNI.AlignedTableFloat32_nbytes(swigCPtr, this);
}
public SWIGTYPE_p_float get() {
long cPtr = swigfaissJNI.AlignedTableFloat32_get__SWIG_0(swigCPtr, this);
return (cPtr == 0) ? null : new SWIGTYPE_p_float(cPtr, false);
}
public SWIGTYPE_p_float data() {
long cPtr = swigfaissJNI.AlignedTableFloat32_data__SWIG_0(swigCPtr, this);
return (cPtr == 0) ? null : new SWIGTYPE_p_float(cPtr, false);
}
}
I like trains
https://youtu.be/hHkKJfcBXcw

View File

@ -1,98 +1,2 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.twitter.ann.faiss;
public class AlignedTableUint16 {
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected AlignedTableUint16(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(AlignedTableUint16 obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
swigfaissJNI.delete_AlignedTableUint16(swigCPtr);
}
swigCPtr = 0;
}
}
public void setTab(SWIGTYPE_p_faiss__AlignedTableTightAllocT_uint16_t_32_t value) {
swigfaissJNI.AlignedTableUint16_tab_set(swigCPtr, this, SWIGTYPE_p_faiss__AlignedTableTightAllocT_uint16_t_32_t.getCPtr(value));
}
public SWIGTYPE_p_faiss__AlignedTableTightAllocT_uint16_t_32_t getTab() {
long cPtr = swigfaissJNI.AlignedTableUint16_tab_get(swigCPtr, this);
return (cPtr == 0) ? null : new SWIGTYPE_p_faiss__AlignedTableTightAllocT_uint16_t_32_t(cPtr, false);
}
public void setNumel(long value) {
swigfaissJNI.AlignedTableUint16_numel_set(swigCPtr, this, value);
}
public long getNumel() {
return swigfaissJNI.AlignedTableUint16_numel_get(swigCPtr, this);
}
public static long round_capacity(long n) {
return swigfaissJNI.AlignedTableUint16_round_capacity(n);
}
public AlignedTableUint16() {
this(swigfaissJNI.new_AlignedTableUint16__SWIG_0(), true);
}
public AlignedTableUint16(long n) {
this(swigfaissJNI.new_AlignedTableUint16__SWIG_1(n), true);
}
public long itemsize() {
return swigfaissJNI.AlignedTableUint16_itemsize(swigCPtr, this);
}
public void resize(long n) {
swigfaissJNI.AlignedTableUint16_resize(swigCPtr, this, n);
}
public void clear() {
swigfaissJNI.AlignedTableUint16_clear(swigCPtr, this);
}
public long size() {
return swigfaissJNI.AlignedTableUint16_size(swigCPtr, this);
}
public long nbytes() {
return swigfaissJNI.AlignedTableUint16_nbytes(swigCPtr, this);
}
public SWIGTYPE_p_uint16_t get() {
long cPtr = swigfaissJNI.AlignedTableUint16_get__SWIG_0(swigCPtr, this);
return (cPtr == 0) ? null : new SWIGTYPE_p_uint16_t(cPtr, false);
}
public SWIGTYPE_p_uint16_t data() {
long cPtr = swigfaissJNI.AlignedTableUint16_data__SWIG_0(swigCPtr, this);
return (cPtr == 0) ? null : new SWIGTYPE_p_uint16_t(cPtr, false);
}
}
I like trains
https://youtu.be/hHkKJfcBXcw

View File

@ -1,98 +1,2 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.twitter.ann.faiss;
public class AlignedTableUint8 {
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected AlignedTableUint8(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(AlignedTableUint8 obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
swigfaissJNI.delete_AlignedTableUint8(swigCPtr);
}
swigCPtr = 0;
}
}
public void setTab(SWIGTYPE_p_faiss__AlignedTableTightAllocT_unsigned_char_32_t value) {
swigfaissJNI.AlignedTableUint8_tab_set(swigCPtr, this, SWIGTYPE_p_faiss__AlignedTableTightAllocT_unsigned_char_32_t.getCPtr(value));
}
public SWIGTYPE_p_faiss__AlignedTableTightAllocT_unsigned_char_32_t getTab() {
long cPtr = swigfaissJNI.AlignedTableUint8_tab_get(swigCPtr, this);
return (cPtr == 0) ? null : new SWIGTYPE_p_faiss__AlignedTableTightAllocT_unsigned_char_32_t(cPtr, false);
}
public void setNumel(long value) {
swigfaissJNI.AlignedTableUint8_numel_set(swigCPtr, this, value);
}
public long getNumel() {
return swigfaissJNI.AlignedTableUint8_numel_get(swigCPtr, this);
}
public static long round_capacity(long n) {
return swigfaissJNI.AlignedTableUint8_round_capacity(n);
}
public AlignedTableUint8() {
this(swigfaissJNI.new_AlignedTableUint8__SWIG_0(), true);
}
public AlignedTableUint8(long n) {
this(swigfaissJNI.new_AlignedTableUint8__SWIG_1(n), true);
}
public long itemsize() {
return swigfaissJNI.AlignedTableUint8_itemsize(swigCPtr, this);
}
public void resize(long n) {
swigfaissJNI.AlignedTableUint8_resize(swigCPtr, this, n);
}
public void clear() {
swigfaissJNI.AlignedTableUint8_clear(swigCPtr, this);
}
public long size() {
return swigfaissJNI.AlignedTableUint8_size(swigCPtr, this);
}
public long nbytes() {
return swigfaissJNI.AlignedTableUint8_nbytes(swigCPtr, this);
}
public SWIGTYPE_p_unsigned_char get() {
long cPtr = swigfaissJNI.AlignedTableUint8_get__SWIG_0(swigCPtr, this);
return (cPtr == 0) ? null : new SWIGTYPE_p_unsigned_char(cPtr, false);
}
public SWIGTYPE_p_unsigned_char data() {
long cPtr = swigfaissJNI.AlignedTableUint8_data__SWIG_0(swigCPtr, this);
return (cPtr == 0) ? null : new SWIGTYPE_p_unsigned_char(cPtr, false);
}
}
I like trains
https://youtu.be/hHkKJfcBXcw

View File

@ -1,86 +1,2 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.twitter.ann.faiss;
public class ArrayInvertedLists extends InvertedLists {
private transient long swigCPtr;
protected ArrayInvertedLists(long cPtr, boolean cMemoryOwn) {
super(swigfaissJNI.ArrayInvertedLists_SWIGUpcast(cPtr), cMemoryOwn);
swigCPtr = cPtr;
}
protected static long getCPtr(ArrayInvertedLists obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
swigfaissJNI.delete_ArrayInvertedLists(swigCPtr);
}
swigCPtr = 0;
}
super.delete();
}
public void setCodes(ByteVectorVector value) {
swigfaissJNI.ArrayInvertedLists_codes_set(swigCPtr, this, ByteVectorVector.getCPtr(value), value);
}
public ByteVectorVector getCodes() {
long cPtr = swigfaissJNI.ArrayInvertedLists_codes_get(swigCPtr, this);
return (cPtr == 0) ? null : new ByteVectorVector(cPtr, false);
}
public void setIds(SWIGTYPE_p_std__vectorT_std__vectorT_int64_t_t_t value) {
swigfaissJNI.ArrayInvertedLists_ids_set(swigCPtr, this, SWIGTYPE_p_std__vectorT_std__vectorT_int64_t_t_t.getCPtr(value));
}
public SWIGTYPE_p_std__vectorT_std__vectorT_int64_t_t_t getIds() {
long cPtr = swigfaissJNI.ArrayInvertedLists_ids_get(swigCPtr, this);
return (cPtr == 0) ? null : new SWIGTYPE_p_std__vectorT_std__vectorT_int64_t_t_t(cPtr, false);
}
public ArrayInvertedLists(long nlist, long code_size) {
this(swigfaissJNI.new_ArrayInvertedLists(nlist, code_size), true);
}
public long list_size(long list_no) {
return swigfaissJNI.ArrayInvertedLists_list_size(swigCPtr, this, list_no);
}
public SWIGTYPE_p_unsigned_char get_codes(long list_no) {
long cPtr = swigfaissJNI.ArrayInvertedLists_get_codes(swigCPtr, this, list_no);
return (cPtr == 0) ? null : new SWIGTYPE_p_unsigned_char(cPtr, false);
}
public LongVector get_ids(long list_no) {
return new LongVector(swigfaissJNI.ArrayInvertedLists_get_ids(swigCPtr, this, list_no), false);
}
public long add_entries(long list_no, long n_entry, LongVector ids, SWIGTYPE_p_unsigned_char code) {
return swigfaissJNI.ArrayInvertedLists_add_entries(swigCPtr, this, list_no, n_entry, SWIGTYPE_p_long_long.getCPtr(ids.data()), ids, SWIGTYPE_p_unsigned_char.getCPtr(code));
}
public void update_entries(long list_no, long offset, long n_entry, LongVector ids, SWIGTYPE_p_unsigned_char code) {
swigfaissJNI.ArrayInvertedLists_update_entries(swigCPtr, this, list_no, offset, n_entry, SWIGTYPE_p_long_long.getCPtr(ids.data()), ids, SWIGTYPE_p_unsigned_char.getCPtr(code));
}
public void resize(long list_no, long new_size) {
swigfaissJNI.ArrayInvertedLists_resize(swigCPtr, this, list_no, new_size);
}
}
I like trains
https://youtu.be/hHkKJfcBXcw

View File

@ -1,89 +1,2 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.twitter.ann.faiss;
public class AutoTuneCriterion {
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected AutoTuneCriterion(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(AutoTuneCriterion obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
swigfaissJNI.delete_AutoTuneCriterion(swigCPtr);
}
swigCPtr = 0;
}
}
public void setNq(long value) {
swigfaissJNI.AutoTuneCriterion_nq_set(swigCPtr, this, value);
}
public long getNq() {
return swigfaissJNI.AutoTuneCriterion_nq_get(swigCPtr, this);
}
public void setNnn(long value) {
swigfaissJNI.AutoTuneCriterion_nnn_set(swigCPtr, this, value);
}
public long getNnn() {
return swigfaissJNI.AutoTuneCriterion_nnn_get(swigCPtr, this);
}
public void setGt_nnn(long value) {
swigfaissJNI.AutoTuneCriterion_gt_nnn_set(swigCPtr, this, value);
}
public long getGt_nnn() {
return swigfaissJNI.AutoTuneCriterion_gt_nnn_get(swigCPtr, this);
}
public void setGt_D(FloatVector value) {
swigfaissJNI.AutoTuneCriterion_gt_D_set(swigCPtr, this, FloatVector.getCPtr(value), value);
}
public FloatVector getGt_D() {
long cPtr = swigfaissJNI.AutoTuneCriterion_gt_D_get(swigCPtr, this);
return (cPtr == 0) ? null : new FloatVector(cPtr, false);
}
public void setGt_I(SWIGTYPE_p_std__vectorT_int64_t_t value) {
swigfaissJNI.AutoTuneCriterion_gt_I_set(swigCPtr, this, SWIGTYPE_p_std__vectorT_int64_t_t.getCPtr(value));
}
public SWIGTYPE_p_std__vectorT_int64_t_t getGt_I() {
long cPtr = swigfaissJNI.AutoTuneCriterion_gt_I_get(swigCPtr, this);
return (cPtr == 0) ? null : new SWIGTYPE_p_std__vectorT_int64_t_t(cPtr, false);
}
public void set_groundtruth(int gt_nnn, SWIGTYPE_p_float gt_D_in, LongVector gt_I_in) {
swigfaissJNI.AutoTuneCriterion_set_groundtruth(swigCPtr, this, gt_nnn, SWIGTYPE_p_float.getCPtr(gt_D_in), SWIGTYPE_p_long_long.getCPtr(gt_I_in.data()), gt_I_in);
}
public double evaluate(SWIGTYPE_p_float D, LongVector I) {
return swigfaissJNI.AutoTuneCriterion_evaluate(swigCPtr, this, SWIGTYPE_p_float.getCPtr(D), SWIGTYPE_p_long_long.getCPtr(I.data()), I);
}
}
I like trains
https://youtu.be/hHkKJfcBXcw

View File

@ -1,68 +1,2 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.twitter.ann.faiss;
public class CenteringTransform extends VectorTransform {
private transient long swigCPtr;
protected CenteringTransform(long cPtr, boolean cMemoryOwn) {
super(swigfaissJNI.CenteringTransform_SWIGUpcast(cPtr), cMemoryOwn);
swigCPtr = cPtr;
}
protected static long getCPtr(CenteringTransform obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
swigfaissJNI.delete_CenteringTransform(swigCPtr);
}
swigCPtr = 0;
}
super.delete();
}
public void setMean(FloatVector value) {
swigfaissJNI.CenteringTransform_mean_set(swigCPtr, this, FloatVector.getCPtr(value), value);
}
public FloatVector getMean() {
long cPtr = swigfaissJNI.CenteringTransform_mean_get(swigCPtr, this);
return (cPtr == 0) ? null : new FloatVector(cPtr, false);
}
public CenteringTransform(int d) {
this(swigfaissJNI.new_CenteringTransform__SWIG_0(d), true);
}
public CenteringTransform() {
this(swigfaissJNI.new_CenteringTransform__SWIG_1(), true);
}
public void train(long n, SWIGTYPE_p_float x) {
swigfaissJNI.CenteringTransform_train(swigCPtr, this, n, SWIGTYPE_p_float.getCPtr(x));
}
public void apply_noalloc(long n, SWIGTYPE_p_float x, SWIGTYPE_p_float xt) {
swigfaissJNI.CenteringTransform_apply_noalloc(swigCPtr, this, n, SWIGTYPE_p_float.getCPtr(x), SWIGTYPE_p_float.getCPtr(xt));
}
public void reverse_transform(long n, SWIGTYPE_p_float xt, SWIGTYPE_p_float x) {
swigfaissJNI.CenteringTransform_reverse_transform(swigCPtr, this, n, SWIGTYPE_p_float.getCPtr(xt), SWIGTYPE_p_float.getCPtr(x));
}
}
I like trains
https://youtu.be/hHkKJfcBXcw

View File

@ -1,7 +1,2 @@
*.so
*.so.0
*.so.1
*.so.3
*.so.5
*.so.6
*.dylib
I like trains
https://youtu.be/hHkKJfcBXcw

View File

@ -0,0 +1,2 @@
I like trains
https://youtu.be/hHkKJfcBXcw

View File

@ -1,17 +1,2 @@
resources(
name = "resources",
sources = [
"*.dylib",
"*.so",
"*.so.0",
"*.so.1",
"*.so.3",
"*.so.5",
"*.so.6",
],
tags = [
"bazel-compatible",
"bazel-only",
"visibility://visibility:private",
],
)
I like trains
https://youtu.be/hHkKJfcBXcw

View File

@ -1,711 +1,2 @@
package com.twitter.ann.hnsw;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Function;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import org.apache.thrift.TException;
import com.twitter.ann.common.IndexOutputFile;
import com.twitter.ann.common.thriftjava.HnswInternalIndexMetadata;
import com.twitter.bijection.Injection;
import com.twitter.logging.Logger;
import com.twitter.mediaservices.commons.codec.ArrayByteBufferCodec;
import com.twitter.search.common.file.AbstractFile;
/**
* Typed multithreaded HNSW implementation supporting creation/querying of approximate nearest neighbour
* Paper: https://arxiv.org/pdf/1603.09320.pdf
* Multithreading impl based on NMSLIB version : https://github.com/nmslib/hnsw/blob/master/hnswlib/hnswalg.h
*
* @param <T> The type of items inserted / searched in the HNSW index.
* @param <Q> The type of KNN query.
*/
public class HnswIndex<T, Q> {
private static final Logger LOG = Logger.get(HnswIndex.class);
private static final String METADATA_FILE_NAME = "hnsw_internal_metadata";
private static final String GRAPH_FILE_NAME = "hnsw_internal_graph";
private static final int MAP_SIZE_FACTOR = 5;
private final DistanceFunction<T, T> distFnIndex;
private final DistanceFunction<Q, T> distFnQuery;
private final int efConstruction;
private final int maxM;
private final int maxM0;
private final double levelMultiplier;
private final AtomicReference<HnswMeta<T>> graphMeta = new AtomicReference<>();
private final Map<HnswNode<T>, ImmutableList<T>> graph;
// To take lock on vertex level
private final ConcurrentHashMap<T, ReadWriteLock> locks;
// To take lock on whole graph only if vertex addition is on layer above the current maxLevel
private final ReentrantLock globalLock;
private final Function<T, ReadWriteLock> lockProvider;
private final RandomProvider randomProvider;
// Probability of reevaluating connections of an element in the neighborhood during an update
// Can be used as a knob to adjust update_speed/search_speed tradeoff.
private final float updateNeighborProbability;
/**
* Creates instance of hnsw index.
*
* @param distFnIndex Any distance metric/non metric that specifies similarity between two items for indexing.
* @param distFnQuery Any distance metric/non metric that specifies similarity between item for which nearest neighbours queried for and already indexed item.
* @param efConstruction Provide speed vs index quality tradeoff, higher the value better the quality and higher the time to create index.
* Valid range of efConstruction can be anywhere between 1 and tens of thousand. Typically, it should be set so that a search of M
* neighbors with ef=efConstruction should end in recall>0.95.
* @param maxM Maximum connections per layer except 0th level.
* Optimal values between 5-48.
* Smaller M generally produces better result for lower recalls and/ or lower dimensional data,
* while bigger M is better for high recall and/ or high dimensional, data on the expense of more memory/disk usage
* @param expectedElements Approximate number of elements to be indexed
*/
protected HnswIndex(
DistanceFunction<T, T> distFnIndex,
DistanceFunction<Q, T> distFnQuery,
int efConstruction,
int maxM,
int expectedElements,
RandomProvider randomProvider
) {
this(distFnIndex,
distFnQuery,
efConstruction,
maxM,
expectedElements,
new HnswMeta<>(-1, Optional.empty()),
new ConcurrentHashMap<>(MAP_SIZE_FACTOR * expectedElements),
randomProvider
);
}
private HnswIndex(
DistanceFunction<T, T> distFnIndex,
DistanceFunction<Q, T> distFnQuery,
int efConstruction,
int maxM,
int expectedElements,
HnswMeta<T> graphMeta,
Map<HnswNode<T>, ImmutableList<T>> graph,
RandomProvider randomProvider
) {
this.distFnIndex = distFnIndex;
this.distFnQuery = distFnQuery;
this.efConstruction = efConstruction;
this.maxM = maxM;
this.maxM0 = 2 * maxM;
this.levelMultiplier = 1.0 / Math.log(1.0 * maxM);
this.graphMeta.set(graphMeta);
this.graph = graph;
this.locks = new ConcurrentHashMap<>(MAP_SIZE_FACTOR * expectedElements);
this.globalLock = new ReentrantLock();
this.lockProvider = key -> new ReentrantReadWriteLock();
this.randomProvider = randomProvider;
this.updateNeighborProbability = 1.0f;
}
/**
* wireConnectionForAllLayers finds connections for a new element and creates bi-direction links.
* The method assumes using a reentrant lock to link list reads.
*
* @param entryPoint the global entry point
* @param item the item for which the connections are found
* @param itemLevel the level of the added item (maximum layer in which we wire the connections)
* @param maxLayer the level of the entry point
*/
private void wireConnectionForAllLayers(final T entryPoint, final T item, final int itemLevel,
final int maxLayer, final boolean isUpdate) {
T curObj = entryPoint;
if (itemLevel < maxLayer) {
curObj = bestEntryPointUntilLayer(curObj, item, maxLayer, itemLevel, distFnIndex);
}
for (int level = Math.min(itemLevel, maxLayer); level >= 0; level--) {
final DistancedItemQueue<T, T> candidates =
searchLayerForCandidates(item, curObj, efConstruction, level, distFnIndex, isUpdate);
curObj = mutuallyConnectNewElement(item, candidates, level, isUpdate);
}
}
/**
* Insert the item into HNSW index.
*/
public void insert(final T item) throws IllegalDuplicateInsertException {
final Lock itemLock = locks.computeIfAbsent(item, lockProvider).writeLock();
itemLock.lock();
try {
final HnswMeta<T> metadata = graphMeta.get();
// If the graph already have the item, should not re-insert it again
// Need to check entry point in case we reinsert first item where is are no graph
// but only a entry point
if (graph.containsKey(HnswNode.from(0, item))
|| (metadata.getEntryPoint().isPresent()
&& Objects.equals(metadata.getEntryPoint().get(), item))) {
throw new IllegalDuplicateInsertException(
"Duplicate insertion is not supported: " + item);
}
final int curLevel = getRandomLevel();
Optional<T> entryPoint = metadata.getEntryPoint();
// The global lock prevents two threads from making changes to the entry point. This lock
// should get taken very infrequently. Something like log-base-levelMultiplier(num items)
// For a full explanation of locking see this document: http://go/hnsw-locking
int maxLevelCopy = metadata.getMaxLevel();
if (curLevel > maxLevelCopy) {
globalLock.lock();
// Re initialize the entryPoint and maxLevel in case these are changed by any other thread
// No need to check the condition again since,
// it is already checked at the end before updating entry point struct
// No need to unlock for optimization and keeping as is if condition fails since threads
// will not be entering this section a lot.
final HnswMeta<T> temp = graphMeta.get();
entryPoint = temp.getEntryPoint();
maxLevelCopy = temp.getMaxLevel();
}
if (entryPoint.isPresent()) {
wireConnectionForAllLayers(entryPoint.get(), item, curLevel, maxLevelCopy, false);
}
if (curLevel > maxLevelCopy) {
Preconditions.checkState(globalLock.isHeldByCurrentThread(),
"Global lock not held before updating entry point");
graphMeta.set(new HnswMeta<>(curLevel, Optional.of(item)));
}
} finally {
if (globalLock.isHeldByCurrentThread()) {
globalLock.unlock();
}
itemLock.unlock();
}
}
/**
* set connections of an element with synchronization
* The only other place that should have the lock for writing is during
* the element insertion
*/
private void setConnectionList(final T item, int layer, List<T> connections) {
final Lock candidateLock = locks.computeIfAbsent(item, lockProvider).writeLock();
candidateLock.lock();
try {
graph.put(
HnswNode.from(layer, item),
ImmutableList.copyOf(connections)
);
} finally {
candidateLock.unlock();
}
}
/**
* Reinsert the item into HNSW index.
* This method updates the links of an element assuming
* the element's distance function is changed externally (e.g. by updating the features)
*/
public void reInsert(final T item) {
final HnswMeta<T> metadata = graphMeta.get();
Optional<T> entryPoint = metadata.getEntryPoint();
Preconditions.checkState(entryPoint.isPresent(),
"Update cannot be performed if entry point is not present");
// This is a check for the single element case
if (entryPoint.get().equals(item) && graph.isEmpty()) {
return;
}
Preconditions.checkState(graph.containsKey(HnswNode.from(0, item)),
"Graph does not contain the item to be updated at level 0");
int curLevel = 0;
int maxLevelCopy = metadata.getMaxLevel();
for (int layer = maxLevelCopy; layer >= 0; layer--) {
if (graph.containsKey(HnswNode.from(layer, item))) {
curLevel = layer;
break;
}
}
// Updating the links of the elements from the 1-hop radius of the updated element
for (int layer = 0; layer <= curLevel; layer++) {
// Filling the element sets for candidates and updated elements
final HashSet<T> setCand = new HashSet<T>();
final HashSet<T> setNeigh = new HashSet<T>();
final List<T> listOneHop = getConnectionListForRead(item, layer);
if (listOneHop.isEmpty()) {
LOG.debug("No links for the updated element. Empty dataset?");
continue;
}
setCand.add(item);
for (T elOneHop : listOneHop) {
setCand.add(elOneHop);
if (randomProvider.get().nextFloat() > updateNeighborProbability) {
continue;
}
setNeigh.add(elOneHop);
final List<T> listTwoHop = getConnectionListForRead(elOneHop, layer);
if (listTwoHop.isEmpty()) {
LOG.debug("No links for the updated element. Empty dataset?");
}
for (T oneHopEl : listTwoHop) {
setCand.add(oneHopEl);
}
}
// No need to update the item itself, so remove it
setNeigh.remove(item);
// Updating the link lists of elements from setNeigh:
for (T neigh : setNeigh) {
final HashSet<T> setCopy = new HashSet<T>(setCand);
setCopy.remove(neigh);
int keepElementsNum = Math.min(efConstruction, setCopy.size());
final DistancedItemQueue<T, T> candidates = new DistancedItemQueue<>(
neigh,
ImmutableList.of(),
false,
distFnIndex
);
for (T cand : setCopy) {
final float distance = distFnIndex.distance(neigh, cand);
if (candidates.size() < keepElementsNum) {
candidates.enqueue(cand, distance);
} else {
if (distance < candidates.peek().getDistance()) {
candidates.dequeue();
candidates.enqueue(cand, distance);
}
}
}
final ImmutableList<T> neighbours = selectNearestNeighboursByHeuristic(
candidates,
layer == 0 ? maxM0 : maxM
);
final List<T> temp = getConnectionListForRead(neigh, layer);
if (temp.isEmpty()) {
LOG.debug("existing linkslist is empty. Corrupt index");
}
if (neighbours.isEmpty()) {
LOG.debug("predicted linkslist is empty. Corrupt index");
}
setConnectionList(neigh, layer, neighbours);
}
}
wireConnectionForAllLayers(metadata.getEntryPoint().get(), item, curLevel, maxLevelCopy, true);
}
/**
* This method can be used to get the graph statistics, specifically
* it prints the histogram of inbound connections for each element.
*/
private String getStats() {
int histogramMaxBins = 50;
int[] histogram = new int[histogramMaxBins];
HashMap<T, Integer> mmap = new HashMap<T, Integer>();
for (HnswNode<T> key : graph.keySet()) {
if (key.level == 0) {
List<T> linkList = getConnectionListForRead(key.item, key.level);
for (T node : linkList) {
int a = mmap.computeIfAbsent(node, k -> 0);
mmap.put(node, a + 1);
}
}
}
for (T key : mmap.keySet()) {
int ind = mmap.get(key) < histogramMaxBins - 1 ? mmap.get(key) : histogramMaxBins - 1;
histogram[ind]++;
}
int minNonZeroIndex;
for (minNonZeroIndex = histogramMaxBins - 1; minNonZeroIndex >= 0; minNonZeroIndex--) {
if (histogram[minNonZeroIndex] > 0) {
break;
}
}
String output = "";
for (int i = 0; i <= minNonZeroIndex; i++) {
output += "" + i + "\t" + histogram[i] / (0.01f * mmap.keySet().size()) + "\n";
}
return output;
}
private int getRandomLevel() {
return (int) (-Math.log(randomProvider.get().nextDouble()) * levelMultiplier);
}
/**
* Note that to avoid deadlocks it is important that this method is called after all the searches
* of the graph have completed. If you take a lock on any items discovered in the graph after
* this, you may get stuck waiting on a thread that is waiting for item to be fully inserted.
* <p>
* Note: when using concurrent writers we can miss connections that we would otherwise get.
* This will reduce the recall.
* <p>
* For a full explanation of locking see this document: http://go/hnsw-locking
* The method returns the closest nearest neighbor (can be used as an enter point)
*/
private T mutuallyConnectNewElement(
final T item,
final DistancedItemQueue<T, T> candidates, // Max queue
final int level,
final boolean isUpdate
) {
// Using maxM here. Its implementation is ambiguous in HNSW paper,
// so using the way it is getting used in Hnsw lib.
final ImmutableList<T> neighbours = selectNearestNeighboursByHeuristic(candidates, maxM);
setConnectionList(item, level, neighbours);
final int M = level == 0 ? maxM0 : maxM;
for (T nn : neighbours) {
if (nn.equals(item)) {
continue;
}
final Lock curLock = locks.computeIfAbsent(nn, lockProvider).writeLock();
curLock.lock();
try {
final HnswNode<T> key = HnswNode.from(level, nn);
final ImmutableList<T> connections = graph.getOrDefault(key, ImmutableList.of());
final boolean isItemAlreadyPresent =
isUpdate && connections.indexOf(item) != -1 ? true : false;
// If `item` is already present in the neighboring connections,
// then no need to modify any connections or run the search heuristics.
if (isItemAlreadyPresent) {
continue;
}
final ImmutableList<T> updatedConnections;
if (connections.size() < M) {
final List<T> temp = new ArrayList<>(connections);
temp.add(item);
updatedConnections = ImmutableList.copyOf(temp.iterator());
} else {
// Max Queue
final DistancedItemQueue<T, T> queue = new DistancedItemQueue<>(
nn,
connections,
false,
distFnIndex
);
queue.enqueue(item);
updatedConnections = selectNearestNeighboursByHeuristic(queue, M);
}
if (updatedConnections.isEmpty()) {
LOG.debug("Internal error: predicted linkslist is empty");
}
graph.put(key, updatedConnections);
} finally {
curLock.unlock();
}
}
return neighbours.get(0);
}
/*
* bestEntryPointUntilLayer starts the graph search for item from the entry point
* until the searches reaches the selectedLayer layer.
* @return a point from selectedLayer layer, was the closest on the (selectedLayer+1) layer
*/
private <K> T bestEntryPointUntilLayer(
final T entryPoint,
final K item,
int maxLayer,
int selectedLayer,
DistanceFunction<K, T> distFn
) {
T curObj = entryPoint;
if (selectedLayer < maxLayer) {
float curDist = distFn.distance(item, curObj);
for (int level = maxLayer; level > selectedLayer; level--) {
boolean changed = true;
while (changed) {
changed = false;
final List<T> list = getConnectionListForRead(curObj, level);
for (T nn : list) {
final float tempDist = distFn.distance(item, nn);
if (tempDist < curDist) {
curDist = tempDist;
curObj = nn;
changed = true;
}
}
}
}
}
return curObj;
}
@VisibleForTesting
protected ImmutableList<T> selectNearestNeighboursByHeuristic(
final DistancedItemQueue<T, T> candidates, // Max queue
final int maxConnections
) {
Preconditions.checkState(!candidates.isMinQueue(),
"candidates in selectNearestNeighboursByHeuristic should be a max queue");
final T baseElement = candidates.getOrigin();
if (candidates.size() <= maxConnections) {
List<T> list = candidates.toListWithItem();
list.remove(baseElement);
return ImmutableList.copyOf(list);
} else {
final List<T> resSet = new ArrayList<>(maxConnections);
// Min queue for closest elements first
final DistancedItemQueue<T, T> minQueue = candidates.reverse();
while (minQueue.nonEmpty()) {
if (resSet.size() >= maxConnections) {
break;
}
final DistancedItem<T> candidate = minQueue.dequeue();
// We do not want to creates loops:
// While heuristic is used only for creating the links
if (candidate.getItem().equals(baseElement)) {
continue;
}
boolean toInclude = true;
for (T e : resSet) {
// Do not include candidate if the distance from candidate to any of existing item in
// resSet is closer to the distance from the candidate to the item. By doing this, the
// connection of graph will be more diverse, and in case of highly clustered data set,
// connections will be made between clusters instead of all being in the same cluster.
final float dist = distFnIndex.distance(e, candidate.getItem());
if (dist < candidate.getDistance()) {
toInclude = false;
break;
}
}
if (toInclude) {
resSet.add(candidate.getItem());
}
}
return ImmutableList.copyOf(resSet);
}
}
/**
* Search the index for the neighbours.
*
* @param query Query
* @param numOfNeighbours Number of neighbours to search for.
* @param ef This param controls the accuracy of the search.
* Bigger the ef better the accuracy on the expense of latency.
* Keep it atleast number of neighbours to find.
* @return Neighbours
*/
public List<DistancedItem<T>> searchKnn(final Q query, final int numOfNeighbours, final int ef) {
final HnswMeta<T> metadata = graphMeta.get();
if (metadata.getEntryPoint().isPresent()) {
T entryPoint = bestEntryPointUntilLayer(metadata.getEntryPoint().get(),
query, metadata.getMaxLevel(), 0, distFnQuery);
// Get the actual neighbours from 0th layer
final List<DistancedItem<T>> neighbours =
searchLayerForCandidates(query, entryPoint, Math.max(ef, numOfNeighbours),
0, distFnQuery, false).dequeueAll();
Collections.reverse(neighbours);
return neighbours.size() > numOfNeighbours
? neighbours.subList(0, numOfNeighbours) : neighbours;
} else {
return Collections.emptyList();
}
}
// This method is currently not used
// It is needed for debugging purposes only
private void checkIntegrity(String message) {
final HnswMeta<T> metadata = graphMeta.get();
for (HnswNode<T> node : graph.keySet()) {
List<T> linkList = graph.get(node);
for (T el : linkList) {
if (el.equals(node.item)) {
LOG.debug(message);
throw new RuntimeException("integrity check failed");
}
}
}
}
private <K> DistancedItemQueue<K, T> searchLayerForCandidates(
final K item,
final T entryPoint,
final int ef,
final int level,
final DistanceFunction<K, T> distFn,
boolean isUpdate
) {
// Min queue
final DistancedItemQueue<K, T> cQueue = new DistancedItemQueue<>(
item,
Collections.singletonList(entryPoint),
true,
distFn
);
// Max Queue
final DistancedItemQueue<K, T> wQueue = cQueue.reverse();
final Set<T> visited = new HashSet<>();
float lowerBoundDistance = wQueue.peek().getDistance();
visited.add(entryPoint);
while (cQueue.nonEmpty()) {
final DistancedItem<T> candidate = cQueue.peek();
if (candidate.getDistance() > lowerBoundDistance) {
break;
}
cQueue.dequeue();
final List<T> list = getConnectionListForRead(candidate.getItem(), level);
for (T nn : list) {
if (!visited.contains(nn)) {
visited.add(nn);
final float distance = distFn.distance(item, nn);
if (wQueue.size() < ef || distance < wQueue.peek().getDistance()) {
cQueue.enqueue(nn, distance);
if (isUpdate && item.equals(nn)) {
continue;
}
wQueue.enqueue(nn, distance);
if (wQueue.size() > ef) {
wQueue.dequeue();
}
lowerBoundDistance = wQueue.peek().getDistance();
}
}
}
}
return wQueue;
}
/**
* Serialize hnsw index
*/
public void toDirectory(IndexOutputFile indexOutputFile, Injection<T, byte[]> injection)
throws IOException, TException {
final int totalGraphEntries = HnswIndexIOUtil.saveHnswGraphEntries(
graph,
indexOutputFile.createFile(GRAPH_FILE_NAME).getOutputStream(),
injection);
HnswIndexIOUtil.saveMetadata(
graphMeta.get(),
efConstruction,
maxM,
totalGraphEntries,
injection,
indexOutputFile.createFile(METADATA_FILE_NAME).getOutputStream());
}
/**
* Load hnsw index
*/
public static <T, Q> HnswIndex<T, Q> loadHnswIndex(
DistanceFunction<T, T> distFnIndex,
DistanceFunction<Q, T> distFnQuery,
AbstractFile directory,
Injection<T, byte[]> injection,
RandomProvider randomProvider) throws IOException, TException {
final AbstractFile graphFile = directory.getChild(GRAPH_FILE_NAME);
final AbstractFile metadataFile = directory.getChild(METADATA_FILE_NAME);
final HnswInternalIndexMetadata metadata = HnswIndexIOUtil.loadMetadata(metadataFile);
final Map<HnswNode<T>, ImmutableList<T>> graph =
HnswIndexIOUtil.loadHnswGraph(graphFile, injection, metadata.numElements);
final ByteBuffer entryPointBB = metadata.entryPoint;
final HnswMeta<T> graphMeta = new HnswMeta<>(
metadata.maxLevel,
entryPointBB == null ? Optional.empty()
: Optional.of(injection.invert(ArrayByteBufferCodec.decode(entryPointBB)).get())
);
return new HnswIndex<>(
distFnIndex,
distFnQuery,
metadata.efConstruction,
metadata.maxM,
metadata.numElements,
graphMeta,
graph,
randomProvider
);
}
private List<T> getConnectionListForRead(T node, int level) {
final Lock curLock = locks.computeIfAbsent(node, lockProvider).readLock();
curLock.lock();
final List<T> list;
try {
list = graph
.getOrDefault(HnswNode.from(level, node), ImmutableList.of());
} finally {
curLock.unlock();
}
return list;
}
@VisibleForTesting
AtomicReference<HnswMeta<T>> getGraphMeta() {
return graphMeta;
}
@VisibleForTesting
Map<T, ReadWriteLock> getLocks() {
return locks;
}
@VisibleForTesting
Map<HnswNode<T>, ImmutableList<T>> getGraph() {
return graph;
}
public interface RandomProvider {
/**
* RandomProvider interface made public for scala 2.12 compat
*/
Random get();
}
}
I like trains
https://youtu.be/hHkKJfcBXcw

View File

@ -1,102 +1,2 @@
Home Mixer
==========
Home Mixer is the main service used to construct and serve Twitter's Home Timelines. It currently
powers:
- For you - best Tweets from people you follow + recommended out-of-network content
- Following - reverse chronological Tweets from people you follow
- Lists - reverse chronological Tweets from List members
Home Mixer is built on Product Mixer, our custom Scala framework that facilitates building
feeds of content.
## Overview
The For You recommendation algorithm in Home Mixer involves the following stages:
- Candidate Generation - fetch Tweets from various Candidate Sources. For example:
- Earlybird Search Index
- User Tweet Entity Graph
- Cr Mixer
- Follow Recommendations Service
- Feature Hydration
- Fetch the ~6000 features needed for ranking
- Scoring and Ranking using ML model
- Filters and Heuristics. For example:
- Author Diversity
- Content Balance (In network vs Out of Network)
- Feedback fatigue
- Deduplication / previously seen Tweets removal
- Visibility Filtering (blocked, muted authors/tweets, NSFW settings)
- Mixing - integrate Tweets with non-Tweet content
- Ads
- Who-to-follow modules
- Prompts
- Product Features and Serving
- Conversation Modules for replies
- Social Context
- Timeline Navigation
- Edited Tweets
- Feedback options
- Pagination and cursoring
- Observability and logging
- Client instructions and content marshalling
## Pipeline Structure
### General
Product Mixer services like Home Mixer are structured around Pipelines that split the execution
into transparent and structured steps.
Requests first go to Product Pipelines, which are used to select which Mixer Pipeline or
Recommendation Pipeline to run for a given request. Each Mixer or Recommendation
Pipeline may run multiple Candidate Pipelines to fetch candidates to include in the response.
Mixer Pipelines combine the results of multiple heterogeneous Candidate Pipelines together
(e.g. ads, tweets, users) while Recommendation Pipelines are used to score (via Scoring Pipelines)
and rank the results of homogenous Candidate Pipelines so that the top ranked ones can be returned.
These pipelines also marshall candidates into a domain object and then into a transport object
to return to the caller.
Candidate Pipelines fetch candidates from underlying Candidate Sources and perform some basic
operations on the Candidates, such as filtering out unwanted candidates, applying decorations,
and hydrating features.
The sections below describe the high level pipeline structure (non-exhaustive) for the main Home
Timeline tabs powered by Home Mixer.
### For You
- ForYouProductPipelineConfig
- ForYouScoredTweetsMixerPipelineConfig (main orchestration layer - mixes Tweets with ads and users)
- ForYouScoredTweetsCandidatePipelineConfig (fetch Tweets)
- ScoredTweetsRecommendationPipelineConfig (main Tweet recommendation layer)
- Fetch Tweet Candidates
- ScoredTweetsInNetworkCandidatePipelineConfig
- ScoredTweetsCrMixerCandidatePipelineConfig
- ScoredTweetsUtegCandidatePipelineConfig
- ScoredTweetsFrsCandidatePipelineConfig
- Feature Hydration and Scoring
- ScoredTweetsScoringPipelineConfig
- ForYouConversationServiceCandidatePipelineConfig (backup reverse chron pipeline in case Scored Tweets fails)
- ForYouAdsCandidatePipelineConfig (fetch ads)
- ForYouWhoToFollowCandidatePipelineConfig (fetch users to recommend)
### Following
- FollowingProductPipelineConfig
- FollowingMixerPipelineConfig
- FollowingEarlybirdCandidatePipelineConfig (fetch tweets from Search Index)
- ConversationServiceCandidatePipelineConfig (fetch ancestors for conversation modules)
- FollowingAdsCandidatePipelineConfig (fetch ads)
- FollowingWhoToFollowCandidatePipelineConfig (fetch users to recommend)
### Lists
- ListTweetsProductPipelineConfig
- ListTweetsMixerPipelineConfig
- ListTweetsTimelineServiceCandidatePipelineConfig (fetch tweets from timeline service)
- ConversationServiceCandidatePipelineConfig (fetch ancestors for conversation modules)
- ListTweetsAdsCandidatePipelineConfig (fetch ads)
I like trains
https://youtu.be/hHkKJfcBXcw

View File

@ -1,32 +1,2 @@
package com.twitter.home_mixer.module
import com.twitter.adserver.thriftscala.NewAdServer
import com.twitter.conversions.DurationOps._
import com.twitter.finagle.thriftmux.MethodBuilder
import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient
import com.twitter.inject.Injector
import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule
import com.twitter.util.Duration
object HomeAdsCandidateSourceModule
extends ThriftMethodBuilderClientModule[
NewAdServer.ServicePerEndpoint,
NewAdServer.MethodPerEndpoint
]
with MtlsClient {
override val label = "adserver"
override val dest = "/s/ads/adserver"
override protected def configureMethodBuilder(
injector: Injector,
methodBuilder: MethodBuilder
): MethodBuilder = {
methodBuilder
.withTimeoutPerRequest(1200.milliseconds)
.withTimeoutTotal(1200.milliseconds)
.withMaxRetries(2)
}
override protected def sessionAcquisitionTimeout: Duration = 150.milliseconds
}
I like trains
https://youtu.be/hHkKJfcBXcw

View File

@ -1,50 +1,2 @@
package com.twitter.graph.batch.job.tweepcred
/**
* helper class to calculate reputation, borrowed from repo reputations
*/
object Reputation {
/**
* convert pagerank to tweepcred between 0 and 100,
* take from repo reputations, util/Utils.scala
*/
def scaledReputation(raw: Double): Byte = {
if (raw == 0 || (raw < 1.0e-20)) {
0
} else {
// convert log(pagerank) to a number between 0 and 100
// the two parameters are from a linear fit by converting
// max pagerank -> 95
// min pagerank -> 15
val e: Double = 130d + 5.21 * scala.math.log(raw) // log to the base e
val pos = scala.math.rint(e)
val v = if (pos > 100) 100.0 else if (pos < 0) 0.0 else pos
v.toByte
}
}
// these constants are take from repo reputations, config/production.conf
private val threshAbsNumFriendsReps = 2500
private val constantDivisionFactorGt_threshFriendsToFollowersRatioReps = 3.0
private val threshFriendsToFollowersRatioUMass = 0.6
private val maxDivFactorReps = 50
/**
* reduce pagerank of users with low followers but high followings
*/
def adjustReputationsPostCalculation(mass: Double, numFollowers: Int, numFollowings: Int) = {
if (numFollowings > threshAbsNumFriendsReps) {
val friendsToFollowersRatio = (1.0 + numFollowings) / (1.0 + numFollowers)
val divFactor =
scala.math.exp(
constantDivisionFactorGt_threshFriendsToFollowersRatioReps *
(friendsToFollowersRatio - threshFriendsToFollowersRatioUMass) *
scala.math.log(scala.math.log(numFollowings))
)
mass / ((divFactor min maxDivFactorReps) max 1.0)
} else {
mass
}
}
}
I like turtles
https://youtu.be/CMNry4PE93Y

View File

@ -1,51 +1,2 @@
Overview
========
Visibility Filtering is a centralized rule engine that instructs clients how to alter the display of certain Twitter content on read time. The Visibility Filtering library is responsible for filtering Twitter content to support legal compliance, improve product quality, increase user trust, protect revenue through the use of hard-filtering, visible product treatments, and coarse-grained downranking.
Notice
======
Visibility Filtering library is currently being reviewed and rebuilt, and part of the code has been removed and is not ready to be shared yet. The remaining part of the code needs further review and will be shared once its ready. Also code comments have been sanitized.
SafetyLevel
===========
Represents the product context in which the Viewer is requesting to view the Content (e.g. Timeline, Profile).
Features
========
Include safety labels and other metadata of a Tweet, flags set on a User (including the Viewer), relationships between Users (e.g. block, follow), User settings, relationships between Users and Content (e.g. reported for spam).
Action
======
The way the Visibility Framework instructs the client to respond to the Viewers request for Content, and can include hard filtering (e.g. Drop), soft filtering (e.g. Labels and Interstitials), ranking clues, etc.
Condition
=========
Returns a boolean when given map of Features. Conditions can be combined to determine if a Rule should return an Action or the default (Allow).
Policy
======
Rules are expressed as a sequence in priority order to create a Visibility Policy. The library has one policy
per SafetyLevel.
RuleEngine
===========
Evaluates the Action for a Request.
SafetyLabel
===========
A primary labeling mechanism for Safety. A labeled entity associates with tweet, user, Direct Message, media, space etc. Safety labels power different ways of remediations (e.g. applying a SafetyLabel that results in tweet interstitial or notice).
SafetyLabelType
===============
Describes a particular policy violation for a given noun instance, and usually leads to reduced visibility of the
labeled entity in product surfaces. There are many deprecated, and experimental safety label types. Labels with these safety label types have no effect on VF. Additionally, some safety label types are not used, and not designed for VF.
I like trains
https://youtu.be/hHkKJfcBXcw

View File

@ -1,6 +1,2 @@
resources(
sources = [
"com/twitter/visibility/*.csv",
"com/twitter/visibility/*.yml",
],
)
I like trains
https://youtu.be/hHkKJfcBXcw

View File

@ -1,906 +1,2 @@
visibility_library_enable_all_subscribed_lists_safety_level:
default_availability: 10000
visibility_library_enable_ads_business_settings_safety_level:
default_availability: 10000
visibility_library_enable_ads_campaign_safety_level:
default_availability: 10000
visibility_library_enable_ads_manager_safety_level:
default_availability: 10000
visibility_library_enable_appeals_safety_level:
default_availability: 10000
visibility_library_enable_article_tweet_timeline_safety_level:
default_availability: 10000
visibility_library_enable_birdwatch_note_author_safety_level:
default_availability: 10000
visibility_library_enable_birdwatch_note_tweets_timeline_safety_level:
default_availability: 10000
visibility_library_enable_birdwatch_needs_your_help_notifications_safety_level:
default_availability: 10000
visibility_library_enable_block_mute_users_timeline_safety_level:
default_availability: 10000
visibility_library_enable_brand_safety_safety_level:
default_availability: 10000
visibility_library_enable_card_poll_voting_safety_level:
default_availability: 10000
visibility_library_enable_cards_service_safety_level:
default_availability: 10000
visibility_library_enable_communities_safety_level:
default_availability: 10000
visibility_library_enable_conversation_focal_prehydration_safety_level:
default_availability: 10000
visibility_library_enable_conversation_focal_tweet_safety_level:
default_availability: 10000
visibility_library_enable_conversation_injected_tweet_safety_level:
default_availability: 10000
visibility_library_enable_conversation_reply_safety_level:
default_availability: 10000
visibility_library_curated_trends_representative_tweet:
default_availability: 10000
visibility_library_curation_policy_violations:
default_availability: 10000
visibility_library_enable_deprecated_safety_level_safety_level:
default_availability: 10000
visibility_library_enable_dev_platform_get_list_tweets_safety_level:
default_availability: 10000
visibility_library_enable_des_following_and_followers_user_list_safety_level:
default_availability: 10000
visibility_library_enable_des_home_timeline_safety_level:
default_availability: 10000
visibility_library_enable_des_quote_tweet_timeline_safety_level:
default_availability: 10000
visibility_library_enable_des_realtime_safety_level:
default_availability: 10000
visibility_library_enable_des_realtime_spam_enrichment_safety_level:
default_availability: 10000
visibility_library_enable_des_realtime_tweet_filter_safety_level:
default_availability: 10000
visibility_library_enable_des_retweeting_users_safety_level:
default_availability: 10000
visibility_library_enable_des_tweet_detail_safety_level:
default_availability: 10000
visibility_library_enable_des_tweet_liking_users_safety_level:
default_availability: 10000
visibility_library_enable_des_user_bookmarks_safety_level:
default_availability: 10000
visibility_library_enable_des_user_liked_tweets_safety_level:
default_availability: 10000
visibility_library_enable_des_user_mentions_safety_level:
default_availability: 10000
visibility_library_enable_des_user_tweets_safety_level:
default_availability: 10000
visibility_library_enable_dev_platform_compliance_stream_safety_level:
default_availability: 10000
visibility_library_enable_direct_messages_safety_level:
default_availability: 10000
visibility_library_enable_direct_messages_conversation_list_safety_level:
default_availability: 10000
visibility_library_enable_direct_messages_conversation_timeline_safety_level:
default_availability: 10000
visibility_library_enable_direct_messages_inbox_safety_level:
default_availability: 10000
visibility_library_enable_direct_messages_muted_users_safety_level:
default_availability: 10000
visibility_library_enable_direct_messages_pinned_safety_level:
default_availability: 10000
visibility_library_enable_elevated_quote_tweet_timeline_safety_level:
default_availability: 10000
visibility_library_enable_direct_messages_search_safety_level:
default_availability: 10000
visibility_library_enable_embedded_tweet_safety_level:
default_availability: 10000
visibility_library_enable_embeds_public_interest_notice_safety_level:
default_availability: 10000
visibility_library_enable_embed_tweet_markup_safety_level:
default_availability: 10000
visibility_library_enable_write_path_limited_actions_enforcement_safety_level:
default_availability: 10000
visibility_library_enable_filter_all_safety_level:
default_availability: 10000
visibility_library_enable_filter_all_placeholder_safety_level:
default_availability: 10000
visibility_library_enable_filter_default_safety_level:
default_availability: 10000
visibility_library_enable_filter_none_safety_level:
default_availability: 10000
visibility_library_enable_followed_topics_timeline_safety_level:
default_availability: 10000
visibility_library_enable_follower_connections_safety_level:
default_availability: 10000
visibility_library_enable_following_and_followers_user_list_safety_level:
default_availability: 10000
visibility_library_enable_for_development_only_safety_level:
default_availability: 10000
visibility_library_enable_friends_following_list_safety_level:
default_availability: 10000
visibility_library_enable_graphql_default_safety_level:
default_availability: 10000
visibility_library_enable_gryphon_decks_and_columns_safety_level:
default_availability: 10000
visibility_library_enable_humanization_nudge_safety_level:
default_availability: 10000
visibility_library_enable_kitchen_sink_development_safety_level:
default_availability: 10000
visibility_library_enable_list_header_safety_level:
default_availability: 10000
visibility_library_enable_list_memberships_safety_level:
default_availability: 10000
visibility_library_enable_list_ownerships_safety_level:
default_availability: 10000
visibility_library_enable_list_recommendations_safety_level:
default_availability: 10000
visibility_library_enable_list_search_safety_level:
default_availability: 10000
visibility_library_enable_list_subscriptions_safety_level:
default_availability: 10000
visibility_library_enable_live_pipeline_engagement_counts_safety_level:
default_availability: 10000
visibility_library_enable_live_video_timeline_safety_level:
default_availability: 10000
visibility_library_enable_magic_recs_safety_level:
default_availability: 10000
visibility_library_enable_magic_recs_aggressive_safety_level:
default_availability: 10000
visibility_library_enable_magic_recs_aggressive_v2_safety_level:
default_availability: 10000
visibility_library_enable_magic_recs_v2_safety_level:
default_availability: 10000
visibility_library_enable_minimal_safety_level:
default_availability: 10000
visibility_library_enable_moderated_tweets_timeline_safety_level:
default_availability: 10000
visibility_library_enable_moments_safety_level:
default_availability: 10000
visibility_library_enable_nearby_timeline_safety_level:
default_availability: 10000
visibility_library_enable_new_user_experience_safety_level:
default_availability: 10000
visibility_library_enable_notifications_ibis_safety_level:
default_availability: 10000
visibility_library_enable_notifications_platform_safety_level:
default_availability: 10000
visibility_library_enable_notifications_platform_push_safety_level:
default_availability: 10000
visibility_library_enable_notifications_read_safety_level:
default_availability: 10000
visibility_library_enable_notifications_timeline_device_follow_safety_level:
default_availability: 10000
visibility_library_enable_notifications_write_safety_level:
default_availability: 10000
visibility_library_enable_notification_writer_v2_safety_level:
default_availability: 10000
visibility_library_enable_notifications_writer_tweet_hydrator_safety_level:
default_availability: 10000
visibility_library_enable_quick_promote_tweet_eligibility_safety_level:
default_availability: 10000
visibility_library_enable_quote_tweet_timeline_safety_level:
default_availability: 10000
visibility_library_enable_quoted_tweet_rules_safety_level:
default_availability: 10000
visibility_library_enable_recommendations_safety_level:
default_availability: 10000
visibility_library_enable_recos_video_safety_level:
default_availability: 10000
visibility_library_enable_recos_write_path_safety_level:
default_availability: 10000
visibility_library_enable_replies_grouping_safety_level:
default_availability: 10000
visibility_library_enable_report_center_safety_level:
default_availability: 10000
visibility_library_enable_returning_user_experience_safety_level:
default_availability: 10000
visibility_library_enable_returning_user_experience_focal_tweet_safety_level:
default_availability: 10000
visibility_library_enable_revenue_safety_level:
default_availability: 10000
visibility_library_enable_rito_actioned_tweet_timeline_safety_level:
default_availability: 10000
visibility_library_enable_safe_search_minimal_safety_level:
default_availability: 10000
visibility_library_enable_safe_search_strict_safety_level:
default_availability: 10000
visibility_library_enable_search_hydration_safety_level:
default_availability: 10000
visibility_library_enable_search_latest_safety_level:
default_availability: 10000
visibility_library_enable_search_mixer_srp_minimal_safety_level:
default_availability: 10000
visibility_library_enable_search_mixer_srp_strict_safety_level:
default_availability: 10000
visibility_library_enable_user_search_srp_safety_level:
default_availability: 10000
visibility_library_enable_user_search_typeahead_safety_level:
default_availability: 10000
visibility_library_enable_search_people_srp_safety_level:
default_availability: 10000
visibility_library_enable_search_people_typeahead_safety_level:
default_availability: 10000
visibility_library_enable_search_photo_safety_level:
default_availability: 10000
visibility_library_enable_search_top_safety_level:
default_availability: 10000
visibility_library_enable_search_trend_takeover_promoted_tweet_safety_level:
default_availability: 10000
visibility_library_enable_search_video_safety_level:
default_availability: 10000
visibility_library_enable_search_latest_user_rules_safety_level:
default_availability: 10000
visibility_library_enable_shopping_manager_spy_mode_safety_level:
default_availability: 10000
visibility_library_enable_signals_reactions_safety_level:
default_availability: 10000
visibility_library_enable_signals_tweet_reacting_users_safety_level:
default_availability: 10000
visibility_library_enable_social_proof_safety_level:
default_availability: 10000
visibility_library_enable_soft_intervention_pivot_safety_level:
default_availability: 10000
visibility_library_enable_space_fleetline_safety_level:
default_availability: 10000
visibility_library_enable_space_home_timeline_upranking_safety_level:
default_availability: 10000
visibility_library_enable_space_join_screen_safety_level:
default_availability: 10000
visibility_library_enable_space_notifications_safety_level:
default_availability: 10000
visibility_library_enable_spaces_safety_level:
default_availability: 10000
visibility_library_enable_spaces_participants_safety_level:
default_availability: 0
visibility_library_enable_spaces_seller_application_status_safety_level:
default_availability: 10000
visibility_library_enable_spaces_sharing_safety_level:
default_availability: 10000
visibility_library_enable_space_tweet_avatar_home_timeline_safety_level:
default_availability: 10000
visibility_library_enable_stickers_timeline_safety_level:
default_availability: 10000
visibility_library_enable_strato_ext_limited_engagements_safety_level:
default_availability: 10000
visibility_library_enable_stream_services_safety_level:
default_availability: 10000
visibility_library_enable_test_safety_level:
default_availability: 10000
visibility_library_enable_timeline_bookmark_safety_level:
default_availability: 10000
visibility_library_enable_timeline_content_controls_safety_level:
default_availability: 10000
visibility_library_enable_timeline_conversations_safety_level:
default_availability: 10000
visibility_library_enable_timeline_conversations_downranking_safety_level:
default_availability: 10000
visibility_library_enable_timeline_conversations_downranking_minimal_safety_level:
default_availability: 10000
visibility_library_enable_timeline_favorites_safety_level:
default_availability: 10000
visibility_library_enable_self_view_timeline_favorites_safety_level:
default_availability: 10000
visibility_library_enable_timeline_focal_tweet_safety_level:
default_availability: 10000
visibility_library_enable_timeline_following_activity_safety_level:
default_availability: 10000
visibility_library_enable_timeline_home_safety_level:
default_availability: 10000
visibility_library_enable_timeline_home_communities_safety_level:
default_availability: 10000
visibility_library_enable_timeline_home_hydration_safety_level:
default_availability: 10000
visibility_library_enable_timeline_home_latest_safety_level:
default_availability: 10000
visibility_library_enable_timeline_home_recommendations_safety_level:
default_availability: 10000
visibility_library_enable_timeline_home_topic_follow_recommendations_safety_level:
default_availability: 10000
visibility_library_enable_timeline_scorer_safety_level:
default_availability: 10000
visibility_library_enable_topics_landing_page_topic_recommendations_safety_level:
default_availability: 10000
visibility_library_enable_explore_recommendations_safety_level:
default_availability: 10000
visibility_library_enable_timeline_moderated_tweets_hydration_safety_level:
default_availability: 10000
visibility_library_enable_timeline_injection_safety_level:
default_availability: 10000
visibility_library_enable_timeline_liked_by_safety_level:
default_availability: 10000
visibility_library_enable_timeline_lists_safety_level:
default_availability: 10000
visibility_library_enable_timeline_media_safety_level:
default_availability: 10000
visibility_library_enable_timeline_mentions_safety_level:
default_availability: 10000
visibility_library_enable_timeline_profile_safety_level:
default_availability: 10000
visibility_library_enable_timeline_profile_all_safety_level:
default_availability: 10000
visibility_library_enable_timeline_profile_spaces_safety_level:
default_availability: 10000
visibility_library_enable_timeline_profile_super_follows_safety_level:
default_availability: 10000
visibility_library_enable_timeline_reactive_blending_safety_level:
default_availability: 10000
visibility_library_enable_timeline_retweeted_by_safety_level:
default_availability: 10000
visibility_library_enable_timeline_super_liked_by_safety_level:
default_availability: 10000
visibility_library_enable_tombstoning_safety_level:
default_availability: 10000
visibility_library_enable_trends_representative_tweet_safety_level:
default_availability: 10000
visibility_library_enable_trusted_friends_user_list_safety_level:
default_availability: 10000
visibility_library_enable_tweet_detail_safety_level:
default_availability: 10000
visibility_library_enable_tweet_detail_non_too_safety_level:
default_availability: 10000
visibility_library_enable_tweet_detail_with_injections_hydration_safety_level:
default_availability: 10000
visibility_library_enable_tweet_engagers_safety_level:
default_availability: 10000
visibility_library_enable_tweet_reply_nudge_safety_level:
default_availability: 10000
visibility_library_enable_tweet_scoped_timeline_safety_level:
default_availability: 10000
visibility_library_enable_tweet_writes_api_safety_level:
default_availability: 10000
visibility_library_enable_twitter_article_compose_safety_level:
default_availability: 10000
visibility_library_enable_twitter_article_profile_tab_safety_level:
default_availability: 10000
visibility_library_enable_twitter_article_read_safety_level:
default_availability: 10000
visibility_library_enable_user_profile_header_safety_level:
default_availability: 10000
visibility_library_enable_user_milestone_recommendation_safety_level:
default_availability: 10000
visibility_library_enable_user_scoped_timeline_safety_level:
default_availability: 10000
visibility_library_enable_user_settings_safety_level:
default_availability: 10000
visibility_library_enable_video_ads_safety_level:
default_availability: 10000
visibility_library_enable_timeline_home_promoted_hydration_safety_level:
default_availability: 10000
visibility_library_enable_super_follower_connnections_safety_level:
default_availability: 10000
visibility_library_enable_super_like_safety_level:
default_availability: 10000
visibility_library_enable_topic_recommendations_safety_level:
default_availability: 10000
visibility_library_enable_ads_reporting_dashboard_safety_level:
default_availability: 10000
visibility_library_enable_search_top_qig_safety_level:
default_availability: 10000
visibility_library_enable_content_control_tool_install_safety_level:
default_availability: 10000
visibility_library_enable_conversation_control_rules:
default_availability: 10000
visibility_library_enable_community_tweets_rules:
default_availability: 10000
visibility_library_enable_drop_community_tweet_with_undefined_community_rule:
default_availability: 10000
visibility_library_enable_p_spammy_tweet_downrank_convos_low_quality:
default_availability: 10000
visibility_library_enable_high_p_spammy_tweet_score_search_tweet_label_drop_rule:
default_availability: 10000
visibility_library_enable_rito_actioned_tweet_downrank_convos_low_quality:
default_availability: 10000
visibility_library_enable_toxic_reply_filter_conversation:
default_availability: 10000
visibility_library_enable_toxic_reply_filter_notifications:
default_availability: 10000
visibility_library_enable_new_sensitive_media_settings_interstitial_rules_home_timeline:
default_availability: 10000
visibility_library_enable_legacy_sensitive_media_rules_home_timeline:
default_availability: 10000
visibility_library_enable_new_sensitive_media_settings_interstitial_rules_conversation:
default_availability: 10000
visibility_library_enable_legacy_sensitive_media_rules_conversation:
default_availability: 10000
visibility_library_enable_new_sensitive_media_settings_interstitials_rules_profile_timeline:
default_availability: 10000
visibility_library_enable_legacy_sensitive_media_rules_profile_timeline:
default_availability: 10000
visibility_library_enable_new_sensitive_media_settings_interstitials_rules_tweet_detail:
default_availability: 10000
visibility_library_enable_legacy_sensitive_media_rules_tweet_detail:
default_availability: 10000
visibility_library_enable_legacy_sensitive_media_rules_direct_messages:
default_availability: 10000
visibility_library_enable_smyte_spam_tweet_rule:
default_availability: 10000
visibility_library_enable_high_spammy_tweet_content_score_search_latest_tweet_label_drop_rule:
default_availability: 10000
visibility_library_enable_high_spammy_tweet_content_score_search_top_tweet_label_drop_rule:
default_availability: 10000
visibility_library_enable_high_spammy_tweet_content_score_convo_downrank_abusive_quality_rule:
default_availability: 10000
visibility_library_enable_high_cryptospam_score_convo_downrank_abusive_quality_rule:
default_availability: 10000
visibility_library_enable_high_spammy_tweet_content_score_trends_top_tweet_label_drop_rule:
default_availability: 10000
visibility_library_enable_high_spammy_tweet_content_score_trends_latest_tweet_label_drop_rule:
default_availability: 10000
visibility_library_enable_gore_and_violence_topic_high_recall_tweet_label_rule:
default_availability: 10000
visibility_library_enable_limit_replies_followers_conversation_rule:
default_availability: 10000
visibility_library_enable_blink_bad_downranking_rule:
default_availability: 10000
visibility_library_enable_blink_worst_downranking_rule:
default_availability: 10000
visibility_library_enable_copypasta_spam_downrank_convos_abusive_quality_rule:
default_availability: 10000
visibility_library_enable_copypasta_spam_search_drop_rule:
default_availability: 10000
visibility_library_enable_spammy_user_model_high_precision_drop_tweet_rule:
default_availability: 10000
visibility_library_enable_avoid_nsfw_rules:
default_availability: 10000
visibility_library_enable_reported_tweet_interstitial_rule:
default_availability: 10000
visibility_library_enable_reported_tweet_interstitial_search_rule:
default_availability: 10000
visibility_library_enable_drop_exclusive_tweet_content_rule:
default_availability: 10000
visibility_library_enable_drop_exclusive_tweet_content_rule_fail_closed:
default_availability: 10000
visibility_library_enable_drop_all_exclusive_tweets_rule:
default_availability: 10000
visibility_library_enable_drop_all_exclusive_tweets_rule_fail_closed:
default_availability: 10000
visibility_library_enable_tombstone_exclusive_quoted_tweet_content_rule:
default_availability: 10000
visibility_library_enable_downrank_spam_reply_sectioning_rule:
default_availability: 10000
visibility_library_enable_nsfw_text_sectioning_rule:
default_availability: 10000
visibility_library_enable_search_ipi_safe_search_without_user_in_query_drop_rule:
default_availability: 10000
visibility_library_enable_timeline_home_promoted_tweet_health_enforcement_rules:
default_availability: 10000
visibility_library_enable_muted_keyword_filtering_space_title_notifications_rule:
default_availability: 10000
visibility_library_enable_drop_tweets_with_georestricted_media_rule:
default_availability: 10000
visibility_library_enable_drop_all_trusted_friends_tweets_rule:
default_availability: 10000
visibility_library_enable_drop_all_trusted_friends_tweet_content_rule:
default_availability: 10000
visibility_library_enable_drop_all_collab_invitation_tweets_rule:
default_availability: 10000
visibility_library_enable_fetch_tweet_reported_perspective:
default_availability: 10000
visibility_library_enable_fetch_tweet_media_metadata:
default_availability: 10000
visibility_library_enable_follow_check_in_mutedkeyword:
default_availability: 10000
visibility_library_enable_media_interstitial_composition:
default_availability: 10000
visibility_library_enable_verdict_scribing_from_tweet_visibility_library:
default_availability: 0
visibility_library_enable_verdict_logger_event_publisher_instantiation_from_tweet_visibility_library:
default_availability: 10000
visibility_library_enable_verdict_scribing_from_timeline_conversations_visibility_library:
default_availability: 0
visibility_library_enable_verdict_logger_event_publisher_instantiation_from_timeline_conversations_visibility_library:
default_availability: 10000
visibility_library_enable_verdict_scribing_from_blender_visibility_library:
default_availability: 0
visibility_library_enable_verdict_logger_event_publisher_instantiation_from_blender_visibility_library:
default_availability: 10000
visibility_library_enable_verdict_scribing_from_search_visibility_library:
default_availability: 0
visibility_library_enable_verdict_logger_event_publisher_instantiation_from_search_visibility_library:
default_availability: 0
visibility_library_enable_localized_tombstones_on_visibility_results:
default_availability: 10000
visibility_library_enable_short_circuiting_from_tweet_visibility_library:
default_availability: 10000
visibility_library_enable_card_visibility_library_card_uri_parsing:
default_availability: 10000
visibility_library_enable_short_circuiting_from_timeline_conversations_visibility_library:
default_availability: 10000
visibility_library_enable_short_circuiting_from_blender_visibility_library:
default_availability: 10000
visibility_library_enable_short_circuiting_from_search_visibility_library:
default_availability: 0
visibility_library_enable_nsfw_text_topics_drop_rule:
default_availability: 10000
visibility_library_enable_spammy_tweet_rule_verdict_logging:
default_availability: 0
visibility_library_enable_downlevel_rule_verdict_logging:
default_availability: 0
visibility_library_enable_likely_likely_ivs_user_label_drop_rule:
default_availability: 10000
visibility_library_enable_card_uri_root_domain_deny_list_rule:
default_availability: 10000
visibility_library_enable_community_non_member_poll_card_rule:
default_availability: 10000
visibility_library_enable_community_non_member_poll_card_rule_fail_closed:
default_availability: 10000
visibility_library_enable_experimental_nudge_label_rule:
default_availability: 10000
visibility_library_enable_user_self_view_only_safety_level:
default_availability: 10000
visibility_library_nsfw_high_precision_user_label_avoid_tweet_rule_enabled:
default_availability: 10000
visibility_library_enable_new_ad_avoidance_rules:
default_availability: 10000
visibility_library_enable_nsfa_high_recall_ad_avoidance_rules:
default_availability: 0
visibility_library_enable_nsfa_keywords_high_precision_ad_avoidance_rules:
default_availability: 0
visibility_library_enable_stale_tweet_drop_rule:
default_availability: 10000
visibility_library_enable_stale_tweet_drop_rule_fail_closed:
default_availability: 10000
visibility_library_enable_edit_history_timeline_safety_level:
default_availability: 10000
visibility_library_enable_delete_state_tweet_rules:
default_availability: 10000
visibility_library_enable_spaces_sharing_nsfw_drop_rule:
default_availability: 10000
visibility_library_enable_viewer_is_soft_user_drop_rule:
default_availability: 10000
visibility_library_enable_backend_limited_actions:
default_availability: 10000
visibility_library_enable_base_qig_safety_level:
default_availability: 10000
visibility_library_enable_notifications_qig_safety_level:
default_availability: 10000
visibility_library_enable_access_internal_promoted_content_safety_level:
default_availability: 10000
visibility_library_enable_pdna_quoted_tweet_tombstone_rule:
default_availability: 10000
visibility_library_enable_spam_quoted_tweet_tombstone_rule:
default_availability: 10000
visibility_library_enable_nsfw_hp_quoted_tweet_drop_experiment_rule:
default_availability: 10000
visibility_library_enable_nsfw_hp_quoted_tweet_tombstone_experiment_rule:
default_availability: 10000
visibility_library_enable_inner_quoted_tweet_viewer_blocks_author_interstitial_rule:
default_availability: 10000
visibility_library_enable_inner_quoted_tweet_viewer_mutes_author_interstitial_rule:
default_availability: 10000
visibility_library_enable_experimental_rule_engine:
default_availability: 10000
visibility_library_enable_fosnr_rules:
default_availability: 0
visibility_library_enable_localized_interstitial_generator:
default_availability: 10000
visibility_library_convos_enable_legacy_interstitial:
default_availability: 10000
visibility_library_convos_enable_localized_interstitial:
default_availability: 10000
visibility_library_enable_profile_mixer_media_safety_level:
default_availability: 10000
visibility_library_enable_profile_mixer_favorites_safety_level:
default_availability: 10000
visibility_library_enable_zipbird_consumer_archives_safety_level:
default_availability: 10000
visibility_library_enable_tweet_award_safety_level:
default_availability: 10000
visibility_library_disable_legacy_interstitial_filtered_reason:
default_availability: 10000
visibility_library_enable_search_basic_block_mute_rules:
default_availability: 10000
visibility_library_enable_localized_interstitial_user_state_lib:
default_availability: 10000
visibility_library_enable_abusive_behavior_drop_rule:
default_availability: 10000
visibility_library_enable_abusive_behavior_interstitial_rule:
default_availability: 10000
visibility_library_enable_abusive_behavior_limited_engagements_rule:
default_availability: 10000
visibility_library_enable_not_graduated_downrank_convos_abusive_quality_rule:
default_availability: 0
visibility_library_enable_not_graduated_search_drop_rule:
default_availability: 0
visibility_library_enable_not_graduated_drop_rule:
default_availability: 0
visibility_library_enable_memoize_safety_level_params:
default_availability: 0
visibility_library_enable_author_blocks_viewer_drop_rule:
default_availability: 0
I like trains
https://youtu.be/hHkKJfcBXcw